WebSocket DLL有很多,最近在搞WebSocket服務器,服務端用的是SuperSocket.WebSocket,客戶端封裝在Dll里面供第三方調用,如果dll里面引用第三方框架WebSocket的話,引用dll時還需要引用一堆額外的包,這就顯得有點臃腫,因為dll里面的WebSocket只有客戶端,所以考慮用原生的ClientWebSocket即可;
連接並發送消息:
public class SocketClient { public static ClientWebSocket clientWebSocket; public static Uri serverUri; public SocketClient(string ip, int port) { var webSocketUrl = $@"ws://{ip}:{port}"; clientWebSocket = new ClientWebSocket(); serverUri = new Uri(webSocketUrl); clientWebSocket.ConnectAsync(serverUri, CancellationToken.None).Wait(); } public async Task SendMessageAsync(string Msg) { if (clientWebSocket.State != WebSocketState.Open) { await clientWebSocket.ConnectAsync(serverUri, CancellationToken.None); } if (clientWebSocket.State == WebSocketState.Open) { ArraySegment<byte> bytesToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(Msg)); await clientWebSocket.SendAsync(bytesToSend, WebSocketMessageType.Text, true, CancellationToken.None); } } }
接收消息
ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[1024]); WebSocketReceiveResult result = await ws.ReceiveAsync(bytesReceived, CancellationToken.None); Console.WriteLine(Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count));
ClientWebSocket里面的方法都是異步的,如果同步方法調用異步:
1.不需要獲取返回值的:
clientWebSocket.ConnectAsync(serverUri, CancellationToken.None).Wait();
2.需要獲取返回值的
var result = clientWebSocket.ConnectAsync(serverUri, CancellationToken.None).GetAwaiter().GetResult();
因為是引用dll發送給服務器的,當主線程關閉前一刻發送信息給服務器可能接收不到最后面那條數據,原因是鏈接已經關閉了,發送信息失敗,為確保信息能接收可以定義結束命令,在發送結束命令后程序休眠兩秒,或者全局定義,每次發送信息都休眠一會。
更新:代理問題
WebSocket客戶端一般都是Web的JS,在控制台搞客戶端最簡單的方法是引用第三方的包,像WebSocket4Net,websocket-sharp等,用第三方的包越過代理可以直接在設置里面這樣操作:
而如果用原生的ClientWebSocket的話上面的越過代理方式就不行了,即使設置了也會報403的錯誤:
System.AggregateException:“One or more errors occurred. (The server returned status code '403' when status code '101' was expected.)”
琢磨了老半天后面無意試一下:
clientWebSocket.Options.Proxy = null;
居然就連接成功了。
示例:
static void Main(string[] args) { ClientWebSocket clientWebSocket = new ClientWebSocket(); var webSocketUrl = $@"ws://10.88.22.62:6008"; var serverUri = new Uri(webSocketUrl); clientWebSocket.Options.Proxy = null; clientWebSocket.ConnectAsync(serverUri, CancellationToken.None).Wait(); Console.ReadKey(); }
更新:ClientWebSocket不支持win7系統,由於要用到我去挖了第三方庫的底層並將他們實現:C#WebSocket Client底層實現 - 點終將連成線 - 博客園 (cnblogs.com)