代码之家  ›  专栏  ›  技术社区  ›  Basit Anwer

为BeginReceive提供的字节

  •  -1
  • Basit Anwer  · 技术社区  · 14 年前

    我的程序所做的是,在第一次接受连接时,服务器发送数据 客户端接收然后再次发送(数据大小不更改) 服务器接收到它,然后再次发送…循环继续…

    当服务器第二次接收数据时,endReceive()返回的int;为0

    虽然我已经找到了解决方案,但我不知道为什么这确实解决了问题

    我在这里读到有个叫做“脏”缓冲器的东西:s

    所以我所做的就是。

    //added line
    data = new byte[DataSize];
    
    //now index works fine :s
    int index = socket.endreceive(result);
    

    以前我在重复使用 byte[] data 对于不更改其内容的发送和接收,数据发送全部为零。

    它起作用了:)

    在那里,msdn帮不了我,还是我错过了睡眠? MSDN Link

    这是汇总代码

        private void OnSendCallBack(IAsyncResult result)
        {
            int id_client = (int)result.AsyncState;
            try
            {
    
                int index = clientInfo[id_client].client.EndSend(result);
    
                clientInfo[id_client].offsetSend += index;
                if (index == 0)
                {
                    Console.WriteLine("Index == 0");
                    return;
                }
                else if (clientInfo[id_client].offsetSend < DataSize)
                {
                    clientInfo[id_client].dataToSend = DataSize - clientInfo[id_client].offsetSend;
                    clientInfo[id_client].client.BeginSend(data, clientInfo[id_client].offsetSend, clientInfo[id_client].dataToSend, SocketFlags.None, RecieveCallBack, id_client);
                }
                else 
                {
                    clientInfo[id_client].offsetSend = 0;
                    clientInfo[id_client].dataToSend = DataSize;
                    //*************************************
                    data = new byte[DataSize]; // THIS IS THE PROBLEM HERE
                    //*************************************
                    clientInfo[id_client].client.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallBack, id_client);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Send: " + ex.Message);
            }
        }
    
    private void RecieveCallBack(IAsyncResult result)
        {
            int id_client = (int)result.AsyncState;
    
            try
            {
    
                int index = clientInfo[id_client].client.EndReceive(result);
    
                //byte[] buffer = new byte[DataSize];
                //int received = clientInfo[id_client].client.Receive(buffer);
    
                clientInfo[id_client].offsetRec += index;
                if (index == 0)
                {
                    index = clientInfo[id_client].client.EndReceive(result);
                    Console.WriteLine("Index == 0");
                    return;
                }
                else if (clientInfo[id_client].offsetRec < DataSize && clientInfo[id_client].offsetRec != 0)
                {
                    clientInfo[id_client].dataToReceive = DataSize - clientInfo[id_client].offsetRec;
                    clientInfo[id_client].client.BeginReceive(data, clientInfo[id_client].offsetRec, clientInfo[id_client].dataToReceive, SocketFlags.None, RecieveCallBack, id_client);
                }
                else
                {
                    clientInfo[id_client].offsetRec = 0;
                    clientInfo[id_client].dataToReceive = DataSize;
    
                    if (clientInfo[id_client].RunNumber < RounCount)
                    {
                        clientInfo[id_client].RoundTripStat.EndSample();
                        clientInfo[id_client].RoundTripStat.BeginSample(); 
                        clientInfo[id_client].client.BeginSend(data, 0, data.Length, SocketFlags.None, OnSendCallBack, id_client); 
                    }
    
                    Close(id_client);
                }
    
            }
            catch (Exception ex)
            {
                Console.WriteLine("Server: " + ex.Message);
            }
        }
    

    我提供了sendcallback和receive回调的代码,您可以看到一个asynch命令正在一次等待一个。

    1 回复  |  直到 14 年前
        1
  •  1
  •   Jon Skeet    14 年前

    EndReceive() 如果没有更多要接收的数据,并且套接字已关闭(即在那里),则返回0 不再接收数据)。

    从您提到的文档中:

    如果远程主机使用shutdown方法关闭套接字连接,并且已接收到所有可用数据,则endreceive方法将立即完成并返回零字节。

    一般来说,您不应该在发送和接收时重用同一个缓冲区——您最终会发送接收到的任何数据,如果您有重叠的发送和接收异步调用,那么最终可能会处于非常奇怪的状态。

    只有在一次只执行一个操作的情况下才可以安全地“共享”缓冲区,并且确保在写入时,您完全拥有所需的数据,并在其中显式设置。