我正在实现一个小的 ClientWebSocket
来将消息发送到计算机的 IPAddress.Loopback
地址,以便浏览器实用程序页面可以接收它们。但是,一旦我连接,客户端就会立即关闭,没有消息、原因或异常。
ClientWebSocket cws;
Uri address = new Uri("ws://" + IPAddress.Loopback.ToString() + ":80/"
async void Start(){
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (cws = new ClientWebSocket()) {
cws.Options.KeepAliveInterval = new TimeSpan(1, 0, 0);
//Start response listener loop
_ = Task.Run(() => async_ListenerLoop(receiveCancelTokenSrc.Token).ConfigureAwait(false));
try {
//Start the connection
cws.ConnectAsync(address, sendCancelTokenSrc.Token);
} catch(Exception ex) {
MessageBox.Show("Unable to connect.\n\r\n\r" + ex.Message);
}
}
}
async Task async_ListenerLoop(CancellationToken cancelToken) {
ArraySegment<byte> buffer = WebSocket.CreateServerBuffer(RECIEVE_BUFFER);
List<byte> rawData = new List<byte>();
try {
while (state != WebSocketState.Closed && state != WebSocketState.Aborted && !cancelToken.IsCancellationRequested) {
if(state == WebSocketState.Connecting) {
//Sometimes it waits 2-3 cycles, other times it closes immediately
await Task.Delay(500);
continue;
}
WebSocketReceiveResult receiveResult = await cws.ReceiveAsync(buffer, cancelToken);
if (!cancelToken.IsCancellationRequested) {
if (state == WebSocketState.CloseReceived && receiveResult.MessageType == WebSocketMessageType.Close) {
sendCancelTokenSrc.Cancel();
await cws.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Acknowledge Close frame", CancellationToken.None);
//The socket state changes to closed at this point
}
if (state == WebSocketState.Open) {
if (receiveResult.MessageType == WebSocketMessageType.Text) {
rawData.AddRange(buffer.Array);
if (receiveResult.EndOfMessage) {
string strData = Encoding.UTF8.GetString(rawData.ToArray(), 0, rawData.Count);
ProcessData(JsonConvert.DeserializeObject<RequestDigest>(strData));
rawData.Clear();
}
} else if (receiveResult.MessageType == WebSocketMessageType.Binary) {
rawData.AddRange(buffer.Array);
if (receiveResult.EndOfMessage) {
ProcessData(rawData.ToArray());
rawData.Clear();
}
}
}
}
}
//Descripion is always null
MessageBox.Show("Connection was closed because '"+cws.CloseStatusDescription+"'");
} catch (OperationCanceledException ex) {
// normal upon task/token cancellation, disregard
MessageBox.Show("Connection to server cancelled.\n\r\n\r" + ex.Message);
} catch (JsonReaderException ex) {
MessageBox.Show("Unable to read incoming message.\n\r\n\r" + ex.Message);
} catch (Exception ex) {
MessageBox.Show("Unable recieve incoming message.\n\r\n\r" + ex.Message);
} finally {
sendCancelTokenSrc.Cancel();
AbortConnection();
}
}
void AbortConnection() {
// don't leave the socket in any potentially connected state
if (state != WebSocketState.Closed) {
cws.Abort();
}
cws.Dispose();
}
答案 0 :(得分:0)
您的代码可能还有其他问题(连接套接字和客户端需要一些麻烦才能搞定),但有两个明显的问题:
您需要等待 ConnectAsync(...)
的结果,才能停止 Start()
的代码在没有它的情况下同步继续:
await cws.ConnectAsync(address, sendCancelTokenSrc.Token);
并且您需要确保 cws
在完成之前不会被处理掉。 using(cws) { ... }
块将在代码离开花括号(当前立即发生)时处理 cws
,即使您的侦听器仍在运行,并且需要它保持活动状态。
您可以通过等待异步结果(例如提示!来自您的侦听器的最终结果)将代码保留在 using
块中来实现此目的,或者不使用 { {1}} 并在适当的时间手动处理 using
。
还要确保仅在连接调用完成后才启动侦听器,以确保 cws
处于良好状态。
像这样:
cws
而且……您的听众无疑也需要做更多的工作,但以上内容将使您解决眼前的问题(希望如此!)