处理 WinRT StreamSocket 断开连接(服务器端和客户端) [英] Handling WinRT StreamSocket disconnects (both server and client side)

查看:28
本文介绍了处理 WinRT StreamSocket 断开连接(服务器端和客户端)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 Windows 8/WinRT 编写一个应用程序,它使用 StreamSocket API 与服务器进行流式连接.也就是说,服务端将数据流到客户端,有时带有meta标签,可以随时断开连接.

I have an application I'm writing for Windows 8/WinRT that uses the StreamSocket API to do a streaming connection to a server. That is to say, the server streams data to the client, sometimes with meta tags, and can disconnect at any time.

我遇到的问题是我不知道如何检测服务器何时断开连接.StreamSocket 类、其输入或输出流或 DataReader/DataWriter 类上似乎没有任何与连接状态有关的事件或属性.

The problem I'm having is that I have no idea how to detect when the server has disconnected. There don't appear to be any events or properties on the StreamSocket class, either its input or output streams, or on the DataReader/DataWriter classes that have anything to do with connection status.

最重要的是,在服务器端与客户端断开连接后,DataReader 方法 ReadAsync 不会失败.相反,据我所知,操作成功了,它填充到其缓冲区中的数据只是服务器发送给它的最后一件事(即它没有清除其内部缓冲区,即使我可以看到它已消耗"每次调用 ReadByte 时的缓冲区).它为每次对 ReadAsync 的后续调用执行此操作 - 用服务器在断开连接之前最后发送的内容重新填充缓冲区.这是代码的简化版本:

On top of that, the DataReader method ReadAsync is not failing after the server side disconnects from the client. Instead, the operation succeeds as far as I can tell, and the data it fills into its buffer is just the last thing the server sent to it (i.e. it's not clearing its internal buffer, even though I can see that it has "consumed" the buffer each time I call ReadByte). It does this for every subsequent call to ReadAsync - refilling the buffer with what the server sent last before it disconnected. Here is a simplified version of the code:

    public async Task TestSocketConnectionAsync()
    {
        var socket = new StreamSocket();
        await socket.ConnectAsync(new HostName(Host), Port.ToString(),
            SocketProtectionLevel.PlainSocket);
        var dr = new DataReader(socket.InputStream);
        dr.InputStreamOptions = InputStreamOptions.Partial;

        this.cts = new CancellationTokenSource();
        this.listenerOperation = StartListeningAsync(dr, cts);
    }

    public async Task StartListeningAsync(DataReader dr, CancellationTokenSource cts)
    {
        var token = cts.Token;
        while (true)
        {
            token.ThrowIfCancellationRequested();
            var readOperation = dr.LoadAsync(1024);
            var result = await readOperation;
            if (result <= 0 || readOperation.Status != Windows.Foundation.AsyncStatus.Completed)
            {
                cts.Cancel(); // never gets called, status is always Completed, result always > 0
            }
            else
            {
                while (dr.UnconsumedBufferLength > 0)
                {
                    byte nextByte = dr.ReadByte();

                    // DriveStateMachine(nextByte);
                }
            }
        }
    }

推荐答案

也就是说,服务器将数据流式传输到客户端,有时带有元标记,并且可以随时断开连接.我遇到的问题是我不知道如何检测服务器何时断开连接.

That is to say, the server streams data to the client, sometimes with meta tags, and can disconnect at any time. The problem I'm having is that I have no idea how to detect when the server has disconnected.

优雅"的套接字关闭可以被另一方检测为长度为 0 的读取.也就是说,它就像一个常规的流结束.

A "graceful" socket closure can be detected by the other side as a 0-length read. That is, it just acts like a regular end-of-stream.

中止"的套接字关闭更加棘手.您必须发送数据来检测另一边已经关闭,一旦写入失败,任何额外的读取或写入都应该失败(有一个例外).如果您的协议不允许您发送数据,那么您将不得不在超时到期后假设连接不良并关闭它.:(

An "abortive" socket closure is more tricky. You have to send data to detect that the other side has closed, and once that write fails, any additional reads or writes should fail (with an exception). If your protocol doesn't permit you to send data, then you'll have to assume the connection is bad after a timeout expires and just close it. :(

根据应用程序,中止"套接字关闭可能是正常 - 特别是,可能会编写非常繁忙的服务器来钳制关闭它们的连接,因为它允许它们更快地回收资源(避免 em>四步套接字关闭握手).

Depending on the application "abortive" socket closure may be normal - in particular, very busy servers may be written to clamp shut their connections because it allows them to reclaim resources more quickly (avoiding the four-step socket shutdown handshake).

StreamSocket 类、其输入或输出流或 DataReader/DataWriter 类上似乎没有任何与连接状态有关的事件或属性.

There don't appear to be any events or properties on the StreamSocket class, either its input or output streams, or on the DataReader/DataWriter classes that have anything to do with connection status.

DataReader/DataWriter 不关心连接".它们实际上只是 BitConverter,只是这次设计得更好.

DataReader/DataWriter are not concerned with "connections." They're really just BitConverter, only designed better this time around.

我猜 StreamSocket 没有连接"属性的原因是因为 Socket.Connected 几乎没用,而且绝对是误导.

I would guess that the reason StreamSocket doesn't have a "connected" property is because Socket.Connected is nearly useless and definitely misleading.

我会尝试使用 StreamSocket.InputStream.ReadAsync 直接而不是使用 DataReader,因为无论如何你只是在读取字节.听起来您可能在 DataReader 中发现了一个错误,您应该在 Microsoft Connect 上报告该错误 如果 InputStream.ReadAsync 按预期工作.另请参阅 此相关论坛帖子.

I would try using StreamSocket.InputStream.ReadAsync directly instead of using DataReader, since you are just reading bytes anyway. It sounds like you may have uncovered a bug in DataReader, which you should report on Microsoft Connect if InputStream.ReadAsync works as expected. Also see this related forum post.

这篇关于处理 WinRT StreamSocket 断开连接(服务器端和客户端)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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