如何在客户端检测关闭的 StreamSocket [英] How to detect closed StreamSocket at client side

查看:32
本文介绍了如何在客户端检测关闭的 StreamSocket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

DataReader.LoadAsync does not detect closed sockets (with InputStreamOptions::Partial)

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

I am sending data to server via TCP connection and read the response but after and everything is working here. But after 5-6 message my project is hand I didn't find where is error.

有一段时间我发现连接是通过主机关闭的所以我如何发现StreamSocket是否已连接

Some time i found that connection is closed via host machine so How can i found that is StreamSocket is connected or not

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

============Code=============

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是否已连接

How can i found that is StreamSocket is connected or not

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

I tested your code on my side. DataReader/DataWriter are not concerned with "connections" themself as you known. But the connection closed will be detected by method Task.Wait, which is for synchronized waiting on the task completed or throw exceptions. So in your scenario, if the StreamSocked is closed before DataReader.LoadAsync, the taskLoad.AsTask().Wait(2000); will throw the exception:

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

One or more errors occurred. (An existing connection was forcibly closed by the remote host. )

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

If the socket connection is closed during DataReader.LoadAsync processed, this time the client cannot detect the closing, it will detect the connection closed next time the client send message to server. In your scenario client will continue sending messages to server which will always catch the connection closing when send new messages. You will got connection closed exception at await writer.StoreAsync(); code line if the server close the connection.

但是在 5-6 条消息之后,我的项目已经完成,我没有找到错误所在

But after 5-6 message my project is hand I didn't find where is error

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

You may have catch the exception about connection closing. So this may lead by some other reasons. I saw the DataReader in your code snippet only load message one time for length 1024. So if the message send from server is longer than 1024, the client will receive only partial message, and next time when server send new message, the client will still receive the remain message from the last time not the new message. After several times server will back log many data and may lead issues. I recommend you to update the reader.LoadAsync code as follows:

  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() 方法可以简单地如下:

Addtionaly, I strongly recommend you to use StreamReader instead, which will not have the concern as DataReader has, And your ReadResponse() method can just be simply as follows:

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

关于uwp中StreamSocket的更多细节请参考官方示例.

More details about StreamSocket in uwp please reference the official sample.

这篇关于如何在客户端检测关闭的 StreamSocket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆