【问题标题】:c# TCP socket stops receiving packetc# TCP socket停止接收数据包
【发布时间】:2018-05-23 12:31:04
【问题描述】:

我有一个问题:

我的模型是 1 台服务器同时使用 TCP 套接字模型为多个客户端提供服务。 代码通常可以正常工作并且从不抛出任何异常,但有时服务器和客户端之间的连接会像这样:

+)客户端成功向服务器发送数据(我知道这是因为使用 WireShark 捕获服务器端的每个数据包)

+)Server socket.Receive(buffer) 不显示以上数据。 (为什么?)//它是一个接收循环,所以它必须是零接收之后的一些数据,对吗?但看起来它永远停止接收了。

+)Server 向 Client 发送数据(通常每 500 毫秒发送一次)

+)客户端仍然可以从服务器接收数据

然后循环就这样继续下去。

我需要知道为什么服务器在连接看起来很好的情况下一直“拒绝”来自客户端的(idk)数据?

这是我用于双方的方法 Send:Socket.Send(Encoding.UTF8.GetBytes("Message$");

这是我用于双方的接收方法,请注意每条消息都以“$”结尾以将它们分开。

int Signal(Socket s, byte[] b)
    {
        int k = 0;
        try { k = s.Receive(b); return k; } catch { return 0; }
    }

void Receiverr(Socket s){
     new thread(()=>
     {byte[] byteReceive = new byte[1024];
            Array.Clear(byteReceive, 0, byteReceive.Length);
            while (s.Connected)
            {
                string msg = "";
                int n = Signal(s, byteReceive);
                if (n == 0) { Array.Clear(byteReceive, 0, byteReceive.Length); continue; }
                msg = Encoding.UTF8.GetString(byteReceive);
                textBox2.Text += "n = " + n.ToString() + Environment.NewLine; // i use this to see if any byte that i could miss
                msg = msg.Replace("\0", "");
                string[] arrray_save = msg.Split('$');
                foreach (string message in arrray_save)
                {
                     //do my work
                }
                Array.Clear(byteReceive, 0, byteReceive.Length); continue;
            }
            try{s.Shutdown(SocketShutdown.Both); s.Close();}
            catch{}
     }
  }){isBackGround = true}.Start();       

我已经为此受苦好几个星期了 :(,抱歉英语不好,任何帮助都将不胜感激。

已编辑(2018 年 5 月 24 日) 这是我的新代码,以确保数据正确接收但问题仍然存在

byte[] data_save = new byte[1024]; int index = 0;
while (s.Connected)
            {
                int n = s.Available;
                if (n == 0) { continue; }
                byte[]byteReceive = new byte[n];
                s.Receive(byteReceive);
                byteReceive.CopyTo(data_save, index);
                index += byteReceive.Length;

                string test = Encoding.UTF8.GetString(data_save).Replace("\0", "");
                if (test[test.Length - 1] != '$') { continue; }
                textBox2.Text += test + Environment.NewLine;
                Array.Clear(data_save, 0, data_save.Length);
                index = 0;

                string[] array_save = test.Split('$');
                foreach (string message in array_save)
                {
                     //do my work
                }
         }try { s.Shutdown(SocketShutdown.Both); s.Close();} catch { }

【问题讨论】:

  • 检查客户端是否仍然连接到服务器。很可能是这种情况:服务器断开与客户端的连接,客户端发送了一些确认信息,但由于连接被拒绝,它从未到达服务器。
  • 是的,它仍然配对,这就是为什么“+)客户端仍然能够从服务器接收数据”对吗?
  • 您只写了 3 个步骤,而您在上面发布的那个是第一个。我在问第 1 步和第 2 步之间是否没有断开连接问题。你能确认一下吗?使用调试器代替wireshark。
  • 我已经编辑了一点我的问题,你看到任何提示了吗?

标签: c# tcpsocket


【解决方案1】:

不是正确的套接字读取循环。您似乎假设单个 Receive() 将始终返回完整的消息。 TCP/IP 是一种流协议,没有消息的概念。每个对 Receive 的调用可能少于一条完整的消息。您的服务器必须知道它需要多少字节,或者数据中的某些指示符来指示何时接收到完整的消息。也不要吞下异常。

参见示例

“设计人员最常见的初学者错误之一 TCP/IP 的协议是它们假设消息边界是 保存。例如,他们假设单个“发送”将导致 单个“接收”。”

Message Framing

【讨论】:

  • 由于正在发送的字符串消息使用长度前缀方法来标识字符串长度,因此它们应该引用您在上面提供的 URL 中找到的博客链接 [blog.stephencleary.com/2009/04/…
  • 我可能明白了,正在调查它;以前看过这篇文章,但从没想过是什么导致了我的问题,谢谢你,让我拥抱你
  • 嘿兄弟们,我回来更新了,如果你有时间请看一下
  • 不。那还是坏了。您的代码如何确定已收到完整的消息?
  • 我的每条消息都以字符“$”结尾。所以我将 byteReceive 存储在 []data_save 中,如果编码显示消息以“$”结尾,这意味着我已经收到完整的消息 -> 是时候阅读它们了,否则我会继续为 []data_save 收集更多数据,直到我有足够的时间阅读
【解决方案2】:

如果有人需要,foreach 的线程和事情解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多