【问题标题】:Why does BeginReceive() not return for more than one read?为什么 BeginReceive() 不返回超过一次读取?
【发布时间】:2015-01-04 23:24:39
【问题描述】:

在下面的代码中,我从Main() 调用Receive(),然后调用Async BeginReceive(),并在后台线程中完成接收数据。

问题:对于第一次读取,BeginReceive 成功并附加了 StringBuilder。但是,当再次调用时,永远不会达到if(bytesread>0) 条件,因此我永远不会对收到的数据采取行动。 我希望 BeginReceive 处理多个读取,并且(我认为这与线程有关)我希望 Main() 函数始终侦听来自客户端的新命令(不是新连接,我想保持相同的套接字)。这甚至可能吗?

尝试解决方案:我添加了 ManualResetEvent 以试图阻止 Main() 函数在另一个线程中进行异步读取之前退出。

Main()中的相关代码:

        Receive(server); //await instructions from the client
        done.WaitOne(); //This is a ManualResetEvent.
        Console.ReadLine();

方法定义:

        public static void Receive(Socket server)
    {
        try
        {
            SocketArgs sockargs = new SocketArgs();
            sockargs.handler = server;


             server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);

        }
        catch
        {

        }
    }
    public static void ReceiveCallBack(IAsyncResult ia)
    {
        try
        {
            SocketArgs sockargs = (SocketArgs)ia.AsyncState;
            Socket server = sockargs.handler;
            int BytesRead = server.EndReceive(ia);
            if (BytesRead > 0)
            {
                //Continue reading data.
                sockargs.sb.Append(Encoding.ASCII.GetString(sockargs.buffer, 0, BytesRead));
                MessageBox.Show(sockargs.sb.ToString());
                server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);
            }
            else
            { //Do stuff with sb.ToString()



                done.Set();
            }
        }
        catch(Exception e)
        {
            MessageBox.Show(e.ToString());
        }
    }

【问题讨论】:

  • 您的ReceiveCallback 是否执行过第二次?如果没有,你确定客户端发送了额外的数据吗?
  • 好吧,客户端并没有发送大量数据,只是您可以一次读取的数据。我的问题是,第二次,它应该返回读取的零字节,然后执行我的处理代码。但是,在第二次读取调用中似乎没有达到这一点。
  • 如果客户端断开连接,您只会获得零字节读取。我有一个blog post,它更详细。
  • 好吧,就这样,我需要在主函数中做什么,让处理程序 sock 永远等待更多数据?我尝试了手动重置事件,但奇怪的是它仍然有退出。
  • 即使 MRE 没有阻塞(如果设置了就会出现这种情况),那么ReadLine 肯定会。

标签: c# multithreading sockets asynchronous


【解决方案1】:

重置事件以便WaitOne 再次阻塞。根据 cmets,事件错误地处于设置状态,导致 Main 退出。

【讨论】:

  • 对这将如何解决提问者的问题的更多解释是不容忽视的。就目前而言,这看起来很像评论。
  • 这是根据 cmets 的解决方案。这个答案几乎可以解决问题。
  • 我在留下该评论时正在审查此内容,但看不到该问题的 cmets。请记住,cmets 不一定是永久性的,虽然我确信这个答案会对 OP 有所帮助,但后来偶然发现这个问题和答案的人会从你的智慧中受益。
【解决方案2】:

BytesRead 仅在套接字断开连接时返回零。因此,我的问题的解决方案是简单地处理 else{} 部分中的断开连接。

更多信息可以绑定在这个很有帮助的article

编辑:澄清一下,我在 if() 构造结束时将 BeginReceive() 调用留在那里,因此“总是”发生 BeginReceive() 操作。

【讨论】:

  • 我重新排列了您的帖子,使其看起来不那么仅链接。请检查更改以确保我没有改变您的意图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2017-10-12
  • 1970-01-01
相关资源
最近更新 更多