【问题标题】:How to detect closed StreamSocket at client side如何在客户端检测关闭的StreamSocket
【发布时间】:2016-11-04 17:52:57
【问题描述】:

DataReader.LoadAsync 不检测关闭的套接字(使用 InputStreamOptions::Partial)

我通过 TCP 连接向服务器发送数据并读取响应,但之后一切正常。但是在 5-6 条消息之后,我的项目是手我没有发现错误在哪里。

有时我发现连接是通过主机关闭的 所以 我怎么知道 StreamSocket 是否连接

============代码=============

public async Task<bool> Connect(string host, string port)
        {
            try
            {
                socket = new StreamSocket();
                HostName hostName = new HostName(host);
                CancellationTokenSource _cts = new CancellationTokenSource();
                _cts.CancelAfter(5000);

                // Connect to the server
                await socket.ConnectAsync(hostName, port).AsTask(_cts.Token);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }


        }


      public async Task<String> SendMessageToServer(string message)
            {
                try
                {
                    // Create the data writer object backed by the in-memory stream. 
                    using (writer = new DataWriter(socket.OutputStream))
                    {
                        writer.WriteString(message);
                        await writer.StoreAsync();
                        await writer.FlushAsync();
                        writer.DetachStream();
                        return await ReadResponse();
                    }
                }
                catch (Exception ex)
                {

                    throw ex;
                }

            }
            private async Task<String> ReadResponse()
            {
                DataReader reader;
                StringBuilder strBuilder = new StringBuilder();
                try
                {
                    using (reader = new DataReader(socket.InputStream))
                    {
                        uint ReadBufferLength = 1024;
                        // If task cancellation was requested, comply
                        //cancellationToken.ThrowIfCancellationRequested();
                        // Set InputStreamOptions to complete the asynchronous reask(cancellationToken);
                        reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;

                        IAsyncOperation<uint> taskLoad = reader.LoadAsync(ReadBufferLength);
                        taskLoad.AsTask().Wait(2000);

                        string msg = string.Empty;
                        while (reader.UnconsumedBufferLength > 0)
                        {
                            strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
                            msg = strBuilder.ToString();
                        }

                        reader.DetachStream();
                        reader.Dispose();

                    }
                }
                catch (Exception ex)
                {

                    return "0";
                    throw ex;

                }
                finally
                {
                    // Cleanup once complete


                }
                return strBuilder.ToString();
            }

【问题讨论】:

    标签: c# tcp uwp


    【解决方案1】:

    如何发现 StreamSocket 是否已连接

    我在我这边测试了您的代码。如您所知,DataReader/DataWriter 本身并不关心“连接”。但是连接关闭会被Task.Wait方法检测到,用于同步等待任务完成或抛出异常。所以在你的场景中,如果StreamSockedDataReader.LoadAsync之前关闭,taskLoad.AsTask().Wait(2000);会抛出异常:

    发生了一个或多个错误。 (现有连接被远程主机强行关闭。)

    如果在DataReader.LoadAsync处理过程中socket连接被关闭,这一次客户端检测不到关闭,下次客户端向服务器发送消息时会检测连接关闭。在您的场景中,客户端将继续向服务器发送消息,服务器在发送新消息时总是会捕获连接关闭。如果服务器关闭连接,您将在 await writer.StoreAsync(); 代码行收到连接关闭异常。

    但是在 5-6 条消息之后,我的项目是手我没有找到错误在哪里

    您可能已经捕捉到关于连接关闭的异常。所以这可能是由其他一些原因导致的。我在你的代码sn-p中看到DataReader只加载一次长度为1024的消息。所以如果从服务器发送的消息长于1024,客户端将只收到部分消息,下次服务器发送新消息时,客户端仍然会收到上次的剩余消息,而不是新消息。几次后服务器会返回日志许多数据并可能导致问题。我建议你更新reader.LoadAsync代码如下:

      string msg = string.Empty;  
      var loadsize = await reader.LoadAsync(ReadBufferLength);
      while (loadsize >= ReadBufferLength)
      {
          loadsize = await reader.LoadAsync(ReadBufferLength);
      }
      if (reader.UnconsumedBufferLength > 0)
      {
          strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
      }
    

    另外,我强烈建议你改用StreamReader,不会有DataReader的顾虑,而你的ReadResponse()方法可以简单如下:

    private async Task<String> ReadResponse()
    {
        Stream streamIn = socket.InputStream.AsStreamForRead();
        StreamReader reader2 = new StreamReader(streamIn);
        string response = await reader2.ReadLineAsync();
        return response; 
    } 
    

    更多关于uwp中StreamSocket的细节请参考official sample

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2019-05-13
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多