日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

websocket一直无法链接_.NET Core 实现基于Websocket的在线聊天室

發布時間:2025/3/11 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 websocket一直无法链接_.NET Core 实现基于Websocket的在线聊天室 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是Websocket

我們在傳統的客戶端程序要實現實時雙工通訊第一想到的技術就是socket通訊,但是在web體系是用不了socket通訊技術的,因為http被設計成無狀態,每次跟服務器通訊完成后就會斷開連接。
在沒有websocket之前web系統如果要做雙工通訊往往使用http long polling技術。http long polling 每次往服務器發送請求后,服務端不會立刻返回信息來結束請求,而是一直掛著直到有數據需要返回,或者等待超時了才會返回。客戶端在結束上一次請求后立刻再發送一次請求,如此反復。http long polling雖然能實現web系統的雙工通訊,但是有個很大的問題,就是基于http協議客戶端每次發送請求都需要攜帶巨大的頭部。在并發交互少量數據的時候非常不劃算,對服務器資源的消耗也是巨大的。
websocket很好的改善了以上問題。它基于tcp重新設計了一套協議,同時又兼容http,默認跟http一樣使用80/443端口。websocket鏈接建立本質上就是一次http請求,直接使用http協議的upgrade頭來標識這是一次websocket請求,服務端回復101狀態碼表示“握手”成功。

//客戶端請求

GET / HTTP/1.1

Upgrade: websocket

Connection: Upgrade

Host: example.com

Origin: http://example.com

Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==

Sec-WebSocket-Version: 13

//服務端響應

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=

Sec-WebSocket-Location: ws://example.com/

使用asp.net core來處理websocket

上面我們簡單的了解了websocket,那么如何來使用asp.net core處理websocket呢?因為websocket的握手就是一次http請求,那么我們就可以使用一個middleware來攔截websocket的請求,把建立的鏈接統一進行管理,其實微軟已經幫我們簡單的封裝過了。

新建一個asp.net core網站

新建WebsocketHandlerMiddleware中間件

這個中間件就是我們管理websocket鏈接的入口,我們調用context.WebSockets.AcceptWebSocketAsync()方法把請求轉換為websocket鏈接。

在Invoke方法內接收websocket鏈接

public async Task Invoke(HttpContext context)

{

if (context.Request.Path == "/ws")

{

if (context.WebSockets.IsWebSocketRequest)

{

WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();

string clientId = Guid.NewGuid().ToString(); ;

var wsClient = new WebsocketClient

{

Id = clientId,

WebSocket = webSocket

};

try

{

await Handle(wsClient);

}

catch (Exception ex)

{

_logger.LogError(ex, "Echo websocket client {0} err .", clientId);

await context.Response.WriteAsync("closed");

}

}

else

{

context.Response.StatusCode = 404;

}

}

else

{

await _next(context);

}

}

在Hanle方法等待客戶端的消息

private async Task Handle(WebsocketClient webSocket)

{

WebsocketClientCollection.Add(webSocket);

_logger.LogInformation($"Websocket client added.");

WebSocketReceiveResult result = null;

do

{

var buffer = new byte[1024 * 1];

result = await webSocket.WebSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);

if (result.MessageType == WebSocketMessageType.Text && !result.CloseStatus.HasValue)

{

var msgString = Encoding.UTF8.GetString(buffer);

_logger.LogInformation($"Websocket client ReceiveAsync message {msgString}.");

var message = JsonConvert.DeserializeObject<Message>(msgString);

message.SendClientId = webSocket.Id;

MessageRoute(message);

}

}

while (!result.CloseStatus.HasValue);

WebsocketClientCollection.Remove(webSocket);

_logger.LogInformation($"Websocket client closed.");

}

在MessageRoute方法內對客戶端的消息進行轉發

對客戶端的消息定義幾個標準的action,對不同的action進行特定的處理,比如加入房間、離開房間、在房間內廣播消息等。

private void MessageRoute(Message message)

{

var client = WebsocketClientCollection.Get(message.SendClientId);

switch (message.action)

{

case "join":

client.RoomNo = message.msg;

client.SendMessageAsync($"{message.nick} join room {client.RoomNo} success .");

_logger.LogInformation($"Websocket client {message.SendClientId} join room {client.RoomNo}.");

break;

case "send_to_room":

if (string.IsNullOrEmpty(client.RoomNo))

{

break;

}

var clients = WebsocketClientCollection.GetRoomClients(client.RoomNo);

clients.ForEach(c =>

{

c.SendMessageAsync(message.nick + " : " + message.msg);

});

_logger.LogInformation($"Websocket client {message.SendClientId} send message {message.msg} to room {client.RoomNo}");

break;

case "leave":

var roomNo = client.RoomNo;

client.RoomNo = "";

client.SendMessageAsync($"{message.nick} leave room {roomNo} success .");

_logger.LogInformation($"Websocket client {message.SendClientId} leave room {roomNo}");

break;

default:

break;

}

}

新建WebsocketClientCollection管理類

這個類是個容器,用來存放所有的websocket鏈接,便于統一管理。

public class WebsocketClientCollection

{

private static List<WebsocketClient> _clients = new List<WebsocketClient>();

public static void Add(WebsocketClient client)

{

_clients.Add(client);

}

public static void Remove(WebsocketClient client)

{

_clients.Remove(client);

}

public static WebsocketClient Get(string clientId)

{

var client = _clients.FirstOrDefault(c=>c.Id == clientId);

return client;

}

public static List<WebsocketClient> GetRoomClients(string roomNo)

{

var client = _clients.Where(c => c.RoomNo == roomNo);

return client.ToList();

}

}

在Startup中使用中間件

有了上面的中間件,我們需要use一下。

app.UseWebSockets(new WebSocketOptions

{

KeepAliveInterval = TimeSpan.FromSeconds(60),

ReceiveBufferSize = 1* 1024

});

app.UseMiddleware<WebsocketHandlerMiddleware>();

到此我們的服務端基本完成了,下面進行客戶端html跟JavaScript的編寫。

編寫客戶端界面

修改index.cshtml來實現一個簡單的聊天室ui。

style="margin-bottom:5px;">

room no: type="text" id="txtRoomNo" value="8888"/> id="btnJoin">join room id="btnLeave">leave room

style="margin-bottom:5px;">

nick name: type="text" id="txtNickName" value="batman" />

style="height:300px;width:600px">

style="height:100%;width:100%" id="msgList">

style="text-align: right">

type="text" id="txtMsg" value="" /> id="btnSend">send

使用JavaScript來處理websocket鏈接及消息

現代瀏覽器已經都支持websocket協議,JavaScript運行時內置了WebSocket類,我們僅僅需要new一個Websocket對象出來就可以對websocket進行操作。

var server = 'ws://localhost:5000'; //如果開啟了https則這里是wss

var WEB_SOCKET = new WebSocket(server + '/ws');

WEB_SOCKET.onopen = function (evt) {

console.log('Connection open ...');

$('#msgList').val('websocket connection opened .');

};

WEB_SOCKET.onmessage = function (evt) {

console.log('Received Message: ' + evt.data);

if (evt.data) {

var content = $('#msgList').val();

content = content + '\r\n' + evt.data;

$('#msgList').val(content);

}

};

WEB_SOCKET.onclose = function (evt) {

console.log('Connection closed.');

};

$('#btnJoin').on('click', function () {

var roomNo = $('#txtRoomNo').val();

var nick = $('#txtNickName').val();

if (roomNo) {

var msg = {

action: 'join',

msg: roomNo,

nick: nick

};

WEB_SOCKET.send(JSON.stringify(msg));

}

});

$('#btnSend').on('click', function () {

var message = $('#txtMsg').val();

var nick = $('#txtNickName').val();

if (message) {

WEB_SOCKET.send(JSON.stringify({

action: 'send_to_room',

msg: message,

nick: nick

}));

}

});

$('#btnLeave').on('click', function () {

var nick = $('#txtNickName').val();

var msg = {

action: 'leave',

msg: '',

nick: nick

};

WEB_SOCKET.send(JSON.stringify(msg));

});

運行

至此我們的聊天室已經搭建完成了,運行一下看看效果。我們啟動兩個頁面,進行聊天。可以看到我們的消息被實時的轉發出去了,good job !

源碼

源碼已上傳github?

https://github.com/kklldog/CoreWebsocketChatRoom

關注我的公眾號一起玩轉技術

總結

以上是生活随笔為你收集整理的websocket一直无法链接_.NET Core 实现基于Websocket的在线聊天室的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。