如何在客户端检测关闭的StreamSocket

时间:2016-11-03 14:30:51

标签: c# tcp uwp

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

1 个答案:

答案 0 :(得分:1)

  

我如何才能找到StreamSocket是否已连接

我测试了你的代码。正如您所知,DataReader / DataWriter并不关心自己的“连接”。但是关闭的连接将由方法Task.Wait检测,该方法用于同步等待已完成的任务或抛出异常。因此,在您的方案中,如果StreamSockedDataReader.LoadAsync之前关闭,taskLoad.AsTask().Wait(2000);将抛出异常:

  

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

如果在处理DataReader.LoadAsync期间套接字连接关闭,则此时客户端无法检测到关闭,它将在下次客户端向服务器发送消息时检测到连接已关闭。在您的方案中,客户端将继续向服务器发送消息,这将始终在发送新消息时捕获连接关闭。如果服务器关闭连接,您将在await writer.StoreAsync();代码行处获得连接关闭异常。

  

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

您可能已经捕获关于连接关闭的例外情况。所以这可能由其他一些原因导致。我看到你的代码片段中的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));
  }

Addtionaly,我强烈建议您改为使用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