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

2024-03-13

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

我如何知道 StreamSocket 是否已连接

我在我这边测试了你的代码。如您所知,DataReader/DataWriter 本身并不关心“连接”。但是连接关闭会被方法检测到任务等待 https://msdn.microsoft.com/en-us/library/dd270644(v=vs.110).aspx,用于同步等待任务完成或抛出异常。所以在你的场景中,如果StreamSocked之前已关闭DataReader.LoadAsync https://msdn.microsoft.com/nb-no/library/windows.storage.streams.datareader.loadasync.aspx, the 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));
  }

此外,我强烈建议您使用流阅读器 https://msdn.microsoft.com/en-us/library/system.io.streamreader(v=vs.110).aspx相反,不会有这样的担忧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 的更多详细信息,请参考官方样本 https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/StreamSocket.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐