2017-07-19 114 views
0

背景:外部因素迫使我在C#中实现一个简单的websocket客户端,并且我想保持低的第三方依赖关系的数量。所以如果可能的话,坚持使用System.Net.WebSockets会很好。ClientWebSocket确保消息已经发送并且连接还活着

目标:将一系列JSON对象作为单个消息发送到WebSocket服务器。如果发送失败并发生任何合理的超时,则抛出异常。如果基础TCP连接在新对象变为可用之间断开,则抛出异常。

发送代码:

// ws is an instance of System.Net.WebSockets.ClientWebSocket 
ArraySegment<byte> json = new ArraySegment<byte> 
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data))); 

if (!ws.SendAsync(json, WebSocketMessageType.Binary, true, 
CancellationToken.None).Wait(10000)) 
{ 
    throw new Exception("Error: Websocket send timeout"); 
} 
Console.Write("Sent") 

我这段代码的问题是,当我看到客户端程序打印“已发送”,服务器将不会收到消息,直到SendAsync的几个调用。我的印象是,它滞留在某种内部消息缓冲区中,直到缓冲区溢出。

同样,打破底层TCP连接不会导致下一个SendAsync引发异常,直到以后几条消息。

检查websocket是否存活而不发送: keepalive设置为默认值30s。然而,我从来没有见过wsState会返回除WebSocketState.Open以外的任何内容,即使在断开服务器之后几分钟内,如果我没有任何消息要发送。

我对ClientWebSocket应该如何使用,它根本不起作用,或者我错过文档中的某些细节感到困惑?

+0

你应该使用原始套接字或WebSockets的?如果您使用的是websocket,那么.NET websocket会处理超时,失败和断开的连接。听起来这可能是服务器端的问题。 –

+0

我在服务器上也使用websockets。我不认为这是服务器端问题,但我需要再次验证在排除该选项之前未检测到拔下网线。 – MaVo159

回答

1

你应该await您的异步方法在Task.Run

Task.Run(() => { 
    if (!await ws.SendAsync(json, WebSocketMessageType.Binary, true, 
    CancellationToken.None)) 
    { 
    throw new Exception("Error: Websocket send timeout"); 
    } 
    Console.Write("Sent"); 
}).Wait(10000); 
+0

谢谢。你能澄清一下为什么等待,Task.Run是必要的吗? 我的印象是,等待(10000)应该阻止,直到发送完成或超时?这里有什么等待完成? 关于Task.Run():不会使这段代码再次被阻塞吗?也许我没有在我的问题中说清楚,我希望代码在邮件发送或发送失败之前被阻止。 – MaVo159

+0

对不起,我忘了等待,现在只有在完成后才会写“已发送”,这就是它的全部目的。 – Jimbot

+0

谢谢,这看起来应该工作。但是我仍然对await和.Wait()之间的区别感到困惑。我以为等待和.Wait(-1)会使声明阻塞相同的效果。我最初的尝试有什么问题。 – MaVo159