【问题标题】:How to know whether the socket connection is still alive when using StreamSocket in UWP?在 UWP 中使用 StreamSocket 时如何知道套接字连接是否仍然存在?
【发布时间】:2016-05-16 17:13:28
【问题描述】:

我正在使用StreamSocket 连接到套接字服务器,并且我使用无限循环来读取数据。每条数据都以'\n\n'结尾。 sn-p 如下所示。但是,我无法知道socket是否还活着,而且每次服务器关闭连接时,ReadAsync()都会抛出异常。连接关闭时如何通知?

public async Task<string> ReadData() {
    StreamReader reader = new StreamReader(socket.InputStream.AsStreamForRead());
    char[] ch = new char[65536];
    int i = 0;
    while (IsConnected) {
        await reader.ReadAsync(ch, i++, 1);
        if (i > 1 && ch[i - 1] == '\n' && ch[i - 2] == '\n') break;
    }
    return new StringBuilder().Append(ch, 0, i - 2).ToString();
}

【问题讨论】:

标签: c# sockets win-universal-app


【解决方案1】:

并且每次服务器关闭连接时,ReadAsync() 都会抛出异常。

抛出异常是因为发生了不正常的断开连接。因此,在关闭服务器端的连接之前,请确保套接字上没有任何未决的读取或写入操作,那么应该没有异常。更多详情可以参考StreamSocket class的备注部分。

连接关闭时如何通知?

优雅的套接字关闭可以被另一方检测为 0 长度读取。也就是说,它就像一个常规的流结束。 Here 是一个类似的帖子供您参考。

因此您可以使用以下代码检查您的场景中连接是否关闭:

// break when the connection is closed
if (ch[i - 1] == '\0') break;

以下是我验证过的整个方法:

public async Task<string> ReadData()
{
    StreamReader reader = new StreamReader(socket.InputStream.AsStreamForRead());
    char[] ch = new char[65536];
    int i = 0;
    while (true)
    {
        await reader.ReadAsync(ch, i++, 1);
        // break when the connection is closed or data ends with '\n\n'
        if (ch[i - 1] == '\0' || (i > 1 && ch[i - 1] == '\n' && ch[i - 2] == '\n')) break;
    }

    if (ch[i - 1] == '\0')
    {
        // do something here when the connection is closed
    }
    else
    {
        return new StringBuilder().Append(ch, 0, i - 2).ToString();
    }
}

【讨论】:

    【解决方案2】:

    每次服务器关闭连接时,ReadAsync() 都会抛出异常。

    这对于大多数服务器来说是意料之中的。 TCP/IP 有一个相当昂贵的四部分 握手来优雅地关闭连接,但从服务器的角度来看,等待回收这些资源的时间很长。所以,很多服务器只是“猛击”连接关闭,导致SocketError.ConnectionReset 错误。

    正如我在我的 socket error handling 博客文章中所描述的,如果通信状态使您认为此时“正常关闭”是合适的,那么您还应该同时接受 ConnectionReset 的异常。 (在您的情况下,适当的“关闭”点是消息是否以\n\n 完成)。

    连接关闭时如何通知?

    您将获得ConnectionReset 异常(如果它突然关闭),或者您的ReadAsync 将返回0(如果它正常关闭)。

    不过……

    如何知道socket连接是否还活着?

    只有一种可靠的方法可以检测套接字连接是否仍然可行:向其写入数据。我在half-open problem 上的博客文章中详细介绍了这一点。

    由于套接字通信中的这个相当有趣的怪癖,while (IsConnected) 这样的代码是一种反模式。相反,您需要有一个定期轮询循环,根据计时器发送数据到另一端。

    附:如果可能,请使用 SignalR 而不是原始套接字。他们为您做所有困难的事情。

    【讨论】:

      猜你喜欢
      • 2018-06-10
      • 1970-01-01
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多