TCP-клиент остановлен, пока не отключится от сервера - PullRequest
0 голосов
/ 27 февраля 2019

При попытке получить строку или содержимое файла (в виде строки) через 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");

, пока я не отключусь от серверной стороны.Чем я вижу ожидаемый вывод и клиент отключен.

Вот реализация (оригинал источник )

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);

            //...

, чтобы немедленно начать новое соединениепосле того как сервер отправил некоторые данные и отключил клиента.

1 Ответ

0 голосов
/ 28 февраля 2019

Благодаря помощи Damien_The_Unbeliever и Immersive я смог понять это.Это действительно помогает время от времени читать документы, особенно если вы впервые используете что-то ^^

NetworkStream.Read - это блокирующий вызов и какдокумент doc

возвращает: количество байтов, прочитанных из NetworkStream, или 0, если сокет закрыт .

, поэтому, конечно, *Цикл 1015 * фактически никогда не прерывается.


Так что принятие приведенного там примера сработало для меня, за исключением того, что если сервер завершил соединение, у меня возникла другая проблема, поэтому вместо проверки на _socketConnection.IsConnected я использовал отмеченный ответс этот пост так что все вместе это работает для меня сейчас

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;
}
...