Jer*_*ell 5 c# networking windows-8 windows-runtime
我有一个我正在为Windows 8/WinRT编写的应用程序,它使用StreamSocket API与服务器建立流连接.也就是说,服务器将数据流式传输到客户端,有时使用元标记,并且可以随时断开连接.
我遇到的问题是我不知道如何检测服务器何时断开连接.StreamSocket类(输入或输出流)或与连接状态有关的DataReader/DataWriter类似乎没有任何事件或属性.
最重要的是,在服务器端与客户端断开连接后,DataReader方法ReadAsync不会失败.相反,操作成功,据我所知,它填充到缓冲区的数据只是服务器发送给它的最后一件事(即它没有清除它的内部缓冲区,即使我可以看到它已经"消耗"了每次调用ReadByte时缓冲区.它为每次后续ReadAsync调用执行此操作 - 使用服务器在断开连接之前发送的内容重新填充缓冲区.这是代码的简化版本:
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
也就是说,服务器将数据流式传输到客户端,有时使用元标记,并且可以随时断开连接.我遇到的问题是我不知道如何检测服务器何时断开连接.
另一方可以将"优雅"的套接字闭包检测为0长度读取.也就是说,它就像常规的流末端一样.
"流产"套接字关闭更棘手.您必须发送数据以检测另一方已关闭,并且一旦写入失败,任何其他读取或写入都将失败(有例外).如果您的协议不允许您发送数据,那么在超时到期后您必须假设连接错误并且只是关闭它.:(
取决于应用程序"中止"套接字关闭可能是正常的 - 特别是,可能会编写非常繁忙的服务器来钳位其连接,因为它允许它们更快地回收资源(避免四步套接字关闭握手).
StreamSocket类(输入或输出流)或与连接状态有关的DataReader/DataWriter类似乎没有任何事件或属性.
DataReader/ DataWriter不关心"连接".他们真的只是BitConverter,这次只是设计得更好.
我猜想StreamSocket没有"连接"属性的原因Socket.Connected是因为几乎没用,而且肯定会产生误导.
我会尝试StreamSocket.InputStream.ReadAsync直接使用而不是使用DataReader,因为你只是在读取字节.听起来您可能已经发现了一个错误DataReader,如果按预期工作,您应该报告Microsoft ConnectInputStream.ReadAsync.另请参阅此相关论坛帖子.