【问题标题】:Constant Recieve TcpClient不断接收 TcpClient
【发布时间】:2021-01-03 03:13:01
【问题描述】:

我需要与旧的 Java TCP 服务器通信。 它的工作方式是我需要在请求之后通过发送请求来建立连接 我订阅了事件,服务器通过连接向我发送数据,所以我需要 始终保持监听数据。这就是我所拥有的,它可以工作一段时间,但过了一段时间它就会停止接收。

            string logon = GetLogon();
            client = new TcpClient(SERVER_IP, PORT_NO);
            NetworkStream nwStream = client.GetStream();
            byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(logon);
            nwStream.Write(bytesToSend, 0, bytesToSend.Length);

            while (client.Connected)
            {
                byte[] bytesToRead = new byte[client.ReceiveBufferSize];
                int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
                var message = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
                this.ProcessMessage(message);
            }

我每分钟在一个单独的函数中轮询服务器以检查连接是否打开,即使我没有得到任何数据,它也总是如此。

            bool poll = client.Client.Poll(1000, SelectMode.SelectRead);
            bool data = (client.Client.Available == 0);

这可行,但大约 20 到 60 分钟后,我停止从服务器接收。感谢您的帮助。

【问题讨论】:

  • 将代码放在单独的方法中,当 !client.Connected 在 while 循环之后再次调用该方法
  • 此代码在 Windows 服务中,当 !client.Connected 返回 false 时,服务会重新启动。但在我的情况下 !client.Connected 总是正确的,我只是停止接收数据。
  • 你确定你没有收到数据吗?您如何验证这一点?您的代码是否处理拆分为多个接收的消息?它是否在一个接收到的一组字节中处理两条消息等?
  • 是的,在我建立连接后服务器会向我发送“OK”。我确实收到了一段时间的其他消息。正如您在代码中看到的,我有一个“ProcessMessage()”函数。
  • 从 cmd.exe >Netstat -a 检查连接状态。服务器可能关闭了连接,连接是半开半关的。所以看看 Netstat 是否给出 TimeError。

标签: c# .net tcp


【解决方案1】:

看来我的轮询机制没有保持连接有效。

首先我在套接字上尝试了这个设置。

client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

在那之后,我的轮询机制开始检测到连接在一段时间后断开,但这只会使连接保持活动 2 小时。

然后我偶然发现了这篇文章,它似乎可以解决问题。 https://darchuk.net/2019/01/04/c-setting-socket-keep-alive/

【讨论】:

    【解决方案2】:

    尝试用 try catch 包围您的代码,以便查看是否有任何异常。 另一件事不要使用client.connected,因为它仅在您第一次连接时才更改他的状态,而不是在客户端断开连接时,因此您的循环条件将始终为真。

    试试这个(只需将您的阅读代码放入循环中):

    // Incoming message may be larger than the buffer size.
    do{
         numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
    
         myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
    }
    while(myNetworkStream.DataAvailable);
    

    MSDN NetworkStream.DataAvailable FULL EXAMPLE

    【讨论】:

    • 嗯,我有点需要它始终是正确的,我有另一种方法,每分钟运行一次,检查连接是否打开,如果不是,则处理它,如果你查看第二个代码块这个问题。在过去的一个小时里,我一直在使用 try 块运行它,没有例外。
    • 我添加了一个 if 语句,正如您在 Read() 周围所建议的那样。我尝试在启动服务器 90 分钟后从服务器发送数据,并且成功。我将再等几个小时,然后再将您的答案标记为正确,看看它是否成立。
    • 我必须没问题。我已经使用过这个解决方案,对我来说没问题。
    【解决方案3】:

    我看到了,但连接并不意味着您总是可以读取数据。您没有任何条件可以验证是否有可用数据可供读取。至少在循环中添加一个 if 语句来检查数据的可用性。

    【讨论】:

    • 这可能是个好主意。但是你觉得它解决了一段时间后收不到数据的问题吗?
    猜你喜欢
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 2012-12-04
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多