【问题标题】:TCP Client stalled until disconnected by the serverTCP 客户端停止直到被服务器断开
【发布时间】:2019-07-21 04:46:00
【问题描述】:

当尝试通过 TCP 接收字符串或文件内容(作为字符串)时,我遇到了一个问题,即接收通常可以正常工作,但是

print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");

在我主动断开与服务器端的连接之前,它有点停滞不前。比预期的效果好。

我调试并接收里面的数据

while ((recBytes = netstream.Read(bytes, 0, bytes.Length)) > 0)

循环工作得很好。它还会在正确的时刻结束循环。 但是在那之后什么都没有发生。我没有收到任何错误,没有被“困”在任何循环中,但也没有得到预期的输出

print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");

直到我从服务器端断开连接。比我看到预期的输出和客户端断开连接。

这里是实现(原source

private Thread _tcpThread;
private TcpClient _socketConnection;

public void Connect()
{
    try
    {
        _tcpThread = new Thread(ReciveDataClient);
        _tcpThread.IsBackground = true;
        _tcpThread.Start();
    }
    catch (Exception e)
    {
        print(e.Message);
    }
}

private void ReciveDataClient()
{
    try
    {
        _socketConnection = new TcpClient("xxx.xxx.xxx.xxx", 54321);
        print(this, "TCP -> Connection Success!");
    }
    catch (Exception e)
    {
        print("connection error: " + e.Message)
        return;
    }

    try
    {
        var bytes = new byte[BUFFER_SIZE];

        while (_socketConnection.Connected)
        {
            if (_socketConnection.Available <= 0) continue;

            // Get a stream object for reading              
            var netstream = _socketConnection.GetStream();

            int totalrecbytes = 0;

            int recBytes;
            string file = "";

            // Read incomming stream into byte arrary.                  
            while ((recBytes = netstream.Read(bytes, 0, bytes.Length)) > 0)
            {
                var incommingData = new byte[recBytes];
                Array.Copy(bytes, 0, incommingData, 0, recBytes);
                // Convert byte array to string message.                        
                var serverMessage = Encoding.ASCII.GetString(incommingData);
                file += serverMessage;
                totalrecbytes += recBytes;
            }

            print("TCP -> Data received:\n" + file + "\n\n" + totalrecbytes + " Bytes");

            netstream.Close();
        }

        print("TCP -> connection was terminated by the server");
    }
    catch (Exception e)
    {
        print(e.Message)
        return;
    }
}

我希望我可以保持连接处于活动状态,但仍能正确接收数据并通过持久 TCP 连接与服务器通信。

我在这里遗漏了什么或做错了什么?


到目前为止,我能找到的唯一解决方法是在发送数据后始终断开与服务器端的连接,并在我的代码中将整个 ReceiveDataClient 包装在 while 循环中

private void ReciveDataClient()
{
    while (true)
    {
        try
        {
            _socketConnection = new TcpClient(_server.ToString(), _server.Port);

            //...

为了在服务器发送一些数据并断开客户端后立即开始一个新的连接。

【问题讨论】:

  • "它还会在正确的时刻结束循环。" - 该循环结束的唯一正确时刻是服务器断开连接时。 - NetworkStream.Read - 返回“从 NetworkStream 读取的字节数,如果套接字关闭,则返回 0。” TCP 是一个无限的字节序列(直到套接字关闭)。它是不是消息。
  • 我绝对会推荐使用NetworkStream.Read 文档中的示例来蚕食您的流。大概Read 阻塞,直到有数据或套接字关闭/超时。
  • @Damien_The_Unbeliever 谢谢!不知何故,我错过了NetworkStream.Read 是一个阻塞调用的简单事实:D
  • @Immersive 也感谢示例的提示......它完美地解决了它
  • @Immersive 谢谢我最终可以使用来自this post的标记答案找出答案

标签: c# unity3d tcp tcpclient


【解决方案1】:

感谢 Damien_The_Unbeliever 和 Immersive 的帮助,我可以弄明白。不时阅读文档真的很有帮助,特别是如果这是您第一次使用某些东西^^

NetworkStream.Read 是一个阻塞调用,正如文档所述

返回:从 NetworkStream 读取的字节数,如果套接字关闭,则返回 0。

当然while 循环实际上从未终止。


所以采用那里提供的示例对我有用,除了如果服务器终止连接我遇到了另一个问题,所以我没有检查_socketConnection.IsConnected,而是使用了this post的标记答案,所以现在这一切都适用于我

private Thread _tcpThread;
private TcpClient _socketConnection;

public void Connect()
{
    if(_socketConnection != null) return;

    try
    {
        _tcpThread = new Thread(ReciveDataClient);
        _tcpThread.IsBackground = true;
        _tcpThread.Start();
    }
    catch (Exception e)
    {
        print("TCP -> Thread error: " + e.Message);
    }
}

public void Disconnect()
{
    if(_socketConnection = null) return;

    _tcpThread.Abort();
}

private void ReciveDataClient()
{
    try
    {
        _socketConnection = new TcpClient("xxx.xxx.xxx.xxx", 54321);
        print(this, "TCP -> Connection Success!");
    }
    catch (Exception e)
    {
        print("TCP -> connection error: " + e.Message)
        return;
    }

    try
    {
        while(true)
        {
            // Get a stream object for reading              
            var netstream = _socketConnection.GetStream();

            //Check if still connected                
            if(_socketConnection.Client.Poll(0, SelectMode.SelectRead))
            {
                byte[] buff = new byte[1];
                if( _socketConnection.Client.Receive( buff, SocketFlags.Peek ) == 0 )
                {
                    // Server disconnected or connection lost
                    break;
                }
            }

            // Check to see if this NetworkStream is readable.
            if(myNetworkStream.CanRead)
            {
                byte[] myReadBuffer = new byte[BUFFER_SIZE];
                StringBuilder myCompleteMessage = new StringBuilder();
                int numberOfBytesRead = 0;
                int totalBytesReceived = 0;

                // 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));    
                    totalBytesReceived += numberOfBytesRead;        
                }
                while(myNetworkStream.DataAvailable);

                // Print out the received message to the console.
                print("TCP -> Data received:\n" + myCompleteMessage.ToString() + "\n\n" + totalrecbytes + " Bytes");
            }
            else
            {
                //Prevent a direct loop
                Thread.Sleep(100);
            }          
        }

        print("TCP -> connection was terminated by the server");
    }
    catch(ThreadAbortException)
    {
        print("TCP -> Disconnected");
    }
    catch(Exception e)
    {
        print(e.Message)
    }

    // Clean up
    _socketConnection?.Close();
    _socketConnection?.Dispose();
    _socketConnection = null;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    相关资源
    最近更新 更多