对于想了解Golang实现基于Websocket协议的H5聊天室的读者,本文将提供新的信息,我们将详细介绍golangwebsocket,并且为您提供关于.NETCore基于Websocket的在线聊
对于想了解Golang实现基于Websocket协议的H5聊天室的读者,本文将提供新的信息,我们将详细介绍golang websocket,并且为您提供关于.NET Core 基于Websocket的在线聊天室、.NET Core 基于Websocket的在线聊天室实现、C#基于WebSocket实现聊天室功能、express框架实现基于Websocket建立的简易聊天室的有价值信息。
本文目录一览:- Golang实现基于Websocket协议的H5聊天室(golang websocket)
- .NET Core 基于Websocket的在线聊天室
- .NET Core 基于Websocket的在线聊天室实现
- C#基于WebSocket实现聊天室功能
- express框架实现基于Websocket建立的简易聊天室
Golang实现基于Websocket协议的H5聊天室(golang websocket)
http://www.cnblogs.com/wangrudong003/p/5535689.html
go代码部分:
// WebChat project main.go package main import ( "fmt" "net/http" "time" "encoding/json" "strings" "golang.org/x/net/websocket" ) //全局信息 var datas Datas var users map[*websocket.Conn]string func main() { fmt.Println("启动时间") fmt.Println(time.Now()) //初始化 datas = Datas{} users = make(map[*websocket.Conn]string) //绑定效果页面 http.HandleFunc("/",h_index) //绑定socket方法 http.Handle("/webSocket",websocket.Handler(h_webSocket)) //开始监听 http.ListenAndServe(":8080",nil) } func h_index(w http.ResponseWriter,r *http.Request) { http.ServeFile(w,r,"index.html") } func h_webSocket(ws *websocket.Conn) { var userMsg UserMsg var data string for { //判断是否重复连接 if _,ok := users[ws]; !ok { users[ws] = "匿名" } userMsgsLen := len(datas.UserMsgs) fmt.Println("UserMsgs",userMsgsLen,"users长度:",len(users)) //有消息时,全部分发送数据 if userMsgsLen > 0 { b,errMarshl := json.Marshal(datas) if errMarshl != nil { fmt.Println("全局消息内容异常...") break } for key,_ := range users { errMarshl = websocket.Message.Send(key,string(b)) if errMarshl != nil { //移除出错的链接 delete(users,key) fmt.Println("发送出错...") break } } datas.UserMsgs = make([]UserMsg,0) } fmt.Println("开始解析数据...") err := websocket.Message.Receive(ws,&data) fmt.Println("data:",data) if err != nil { //移除出错的链接 delete(users,ws) fmt.Println("接收出错...") break } data = strings.Replace(data,"\n","",0) err = json.Unmarshal([]byte(data),&userMsg) if err != nil { fmt.Println("解析数据异常...") break } fmt.Println("请求数据类型:",userMsg.DataType) switch userMsg.DataType { case "send": //赋值对应的昵称到ws if _,ok := users[ws]; ok { users[ws] = userMsg.UserName //清除连接人昵称信息 datas.UserDatas = make([]UserData,0) //重新加载当前在线连接人 for _,item := range users { userData := UserData{UserName: item} datas.UserDatas = append(datas.UserDatas,userData) } } datas.UserMsgs = append(datas.UserMsgs,userMsg) } } } type UserMsg struct { UserName string Msg string DataType string } type UserData struct { UserName string } type Datas struct { UserMsgs []UserMsg UserDatas []UserData }
html5代码部分:(index.html 和main.go放置到同一目录)
<!DOCTYPE html> <html lang="zh-CN"> <head> <title></title> <Meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> <!-- 新 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script> <!-- <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>--> </head> <body> <div> <div>内容:</div> <divid="divShow"> <!--<div>1111</div> <div>1111</div> <div>1111</div> <div>1111</div>--> </div> <divid="divUsers"> 在线:<br /> <!--<div>111</div>--> </div> <div> 昵称:<inputid="txtUserName" value="红领巾" type="text" maxlength="20"https://www.jb51.cc/tag/ott/" target="_blank">ottom: 15px" /> 聊聊:<textareaid="txtContent" autofocus rows="6" placeholder="想聊的内容" maxlength="200" required></textarea> <buttonid="btnSend">发 送</button> </div> </div> </body> </html> <script> var tool = function () { var paperLoopNum = 0; var paperTempleArr = [ '<div>{0}</div>','<div>{0}</div>','<div>{0}</div>','<div>{0}</div>' ]; return { paperDiv: function (val) { var hl = paperTempleArr[paperLoopNum]; paperLoopNum++; if (paperLoopNum >= paperTempleArr.length) { paperLoopNum = 0; } return this.formart(hl,[val]) },formart: function (str,arrVal) { for (var i = 0; i < arrVal.length; i++) { str = str.replace("{" + i + "}",arrVal[i]); } return str; } } } function showMsg(id,hl,isAppend) { if (!isAppend) { $("#" + id).html(hl); } else { $("#" + id).append(hl); } } $(function () { //初始化工具方法 var tl = new tool(); var wsUrl = "ws://127.0.0.1:8080/webSocket"; ws = new WebSocket(wsUrl); try { ws.onopen = function () { //showMsg("divShow",tl.paperDiv("连接服务器-成功")); } ws.onclose = function () { if (ws) { ws.close(); ws = null; } showMsg("divShow",tl.paperDiv("连接服务器-关闭"),true); } ws.onmessage = function (result) { //console.log(result.data); var data = JSON.parse(result.data); $(data.UserMsgs).each(function (i,item) { showMsg("divShow",tl.paperDiv("【" + item.UserName + "】:" + item.Msg),true); }); var userDataShow = []; $(data.UserDatas).each(function (i,item) { userDataShow.push('<div>' + item.UserName + '</div>'); }); showMsg("divUsers",userDataShow.join(''),false); } ws.onerror = function () { if (ws) { ws.close(); ws = null; } showMsg("divShow",true); } } catch (e) { alert(e.message); } $("#btnSend").on("click",function () { var tContentObj = $("#txtContent"); var tContent = $.trim( tContentObj.val()).replace("/[\n]/g",""); var tUserName = $.trim( $("#txtUserName").val()); tUserName = tUserName.length <= 0 ? "匿名" : tUserName; if (tContent.length <= 0 || $.trim(tContent).length <= 0) { alert("请输入发送内容!"); return; } if (ws == null) { alert("连接失败,请F5刷新页面!"); return; } var request = tl.formart('{"UserName": "{0}","DataType": "{1}","Msg": "{2}" }',[tUserName,"send",tContent]); ws.send(request); tContentObj.val(""); tContentObj.val($.trim(tContentObj.val()).replace("/[\n]/g","")); }); $("#txtContent").on("keydown",function (event) { if (event.keyCode == 13) { $("#btnSend").trigger("click"); } }); }) </script>
效果图:
下载附件
.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<byte>(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。
<div>
room no: <input type="text" id="txtRoomNo" value="8888"/> <button id="btnJoin">join room</button> <button id="btnLeave">leave room</button>
</div>
<div>
nick name: <input type="text" id="txtNickName" value="batman" />
</div>
<div>
<textareaid="msgList"></textarea>
<div>
<input type="text" id="txtMsg" value="" /> <button id="btnSend">send</button>
</div>
</div>
使用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 CoreWebsocketChatRoom
原文出处:https://www.cnblogs.com/kklldog/p/core-for-websocket.html
.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<byte>(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。
<div> room no: <input type="text" id="txtRoomNo" value="8888"/> <button id="btnJoin">join room</button> <button id="btnLeave">leave room</button> </div> <div> nick name: <input type="text" id="txtNickName" value="batman" /> </div> <div> <textareaid="msgList"></textarea> <div> <input type="text" id="txtMsg" value="" /> <button id="btnSend">send</button> </div> </div>
使用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
CoreWebsocketChatRoom
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- Asp.net Core中如何使用中间件来管理websocket
- Asp.Net Core中WebSocket绑定的方法详解
- NetCore WebSocket即时通讯示例
- 在Asp.net core中实现websocket通信
C#基于WebSocket实现聊天室功能
本文实例为大家分享了C#基于WebSocket实现聊天室功能的具体代码,供大家参考,具体内容如下
前面两篇温习了,C# Socket内容
本章根据Socket异步聊天室修改成WebSocket聊天室
WebSocket特别的地方是 握手和消息内容的编码、解码(添加了ServerHelper协助处理)
ServerHelper:
using System; using System.Collections; using System.Text; using System.Security.Cryptography; namespace SocketDemo { // Server助手 负责:1 握手 2 请求转换 3 响应转换 class ServerHelper { /// <summary> /// 输出连接头信息 /// </summary> public static string ResponseHeader(string requestHeader) { Hashtable table = new Hashtable(); // 拆分成键值对,保存到哈希表 string[] rows = requestHeader.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string row in rows) { int splitIndex = row.IndexOf('':''); if (splitIndex > 0) { table.Add(row.Substring(0, splitIndex).Trim(), row.Substring(splitIndex + 1).Trim()); } } StringBuilder header = new StringBuilder(); header.Append("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"); header.AppendFormat("Upgrade: {0}\r\n", table.ContainsKey("Upgrade") ? table["Upgrade"].ToString() : string.Empty); header.AppendFormat("Connection: {0}\r\n", table.ContainsKey("Connection") ? table["Connection"].ToString() : string.Empty); header.AppendFormat("WebSocket-Origin: {0}\r\n", table.ContainsKey("Sec-WebSocket-Origin") ? table["Sec-WebSocket-Origin"].ToString() : string.Empty); header.AppendFormat("WebSocket-Location: {0}\r\n", table.ContainsKey("Host") ? table["Host"].ToString() : string.Empty); string key = table.ContainsKey("Sec-WebSocket-Key") ? table["Sec-WebSocket-Key"].ToString() : string.Empty; string magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; header.AppendFormat("Sec-WebSocket-Accept: {0}\r\n", Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + magic)))); header.Append("\r\n"); return header.ToString(); } /// <summary> /// 解码请求内容 /// </summary> public static string DecodeMsg(Byte[] buffer, int len) { if (buffer[0] != 0x81 || (buffer[0] & 0x80) != 0x80 || (buffer[1] & 0x80) != 0x80) { return null; } Byte[] mask = new Byte[4]; int beginIndex = 0; int payload_len = buffer[1] & 0x7F; if (payload_len == 0x7E) { Array.Copy(buffer, 4, mask, 0, 4); payload_len = payload_len & 0x00000000; payload_len = payload_len | buffer[2]; payload_len = (payload_len << 8) | buffer[3]; beginIndex = 8; } else if (payload_len != 0x7F) { Array.Copy(buffer, 2, mask, 0, 4); beginIndex = 6; } for (int i = 0; i < payload_len; i++) { buffer[i + beginIndex] = (byte)(buffer[i + beginIndex] ^ mask[i % 4]); } return Encoding.UTF8.GetString(buffer, beginIndex, payload_len); } /// <summary> /// 编码响应内容 /// </summary> public static byte[] EncodeMsg(string content) { byte[] bts = null; byte[] temp = Encoding.UTF8.GetBytes(content); if (temp.Length < 126) { bts = new byte[temp.Length + 2]; bts[0] = 0x81; bts[1] = (byte)temp.Length; Array.Copy(temp, 0, bts, 2, temp.Length); } else if (temp.Length < 0xFFFF) { bts = new byte[temp.Length + 4]; bts[0] = 0x81; bts[1] = 126; bts[2] = (byte)(temp.Length & 0xFF); bts[3] = (byte)(temp.Length >> 8 & 0xFF); Array.Copy(temp, 0, bts, 4, temp.Length); } else { byte[] st = System.Text.Encoding.UTF8.GetBytes(string.Format("暂不处理超长内容").ToCharArray()); } return bts; } } }
Server:
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; namespace SocketDemo { class ClientInfo { public Socket Socket { get; set; } public bool IsOpen { get; set; } public string Address { get; set; } } // 管理Client class ClientManager { static List<ClientInfo> clientList = new List<ClientInfo>(); public static void Add(ClientInfo info) { if (!IsExist(info.Address)) { clientList.Add(info); } } public static bool IsExist(string address) { return clientList.Exists(item => string.Compare(address, item.Address, true) == 0); } public static bool IsExist(string address, bool isOpen) { return clientList.Exists(item => string.Compare(address, item.Address, true) == 0 && item.IsOpen == isOpen); } public static void Open(string address) { clientList.ForEach(item => { if (string.Compare(address, item.Address, true) == 0) { item.IsOpen = true; } }); } public static void Close(string address = null) { clientList.ForEach(item => { if (address == null || string.Compare(address, item.Address, true) == 0) { item.IsOpen = false; item.Socket.Shutdown(SocketShutdown.Both); } }); } // 发送消息到ClientList public static void SendMsgToClientList(string msg, string address = null) { clientList.ForEach(item => { if (item.IsOpen && (address == null || item.Address != address)) { SendMsgToClient(item.Socket, msg); } }); } public static void SendMsgToClient(Socket client, string msg) { byte[] bt = ServerHelper.EncodeMsg(msg); client.BeginSend(bt, 0, bt.Length, SocketFlags.None, new AsyncCallback(SendTarget), client); } private static void SendTarget(IAsyncResult res) { //Socket client = (Socket)res.AsyncState; //int size = client.EndSend(res); } } // 接收消息 class ReceiveHelper { public byte[] Bytes { get; set; } public void ReceiveTarget(IAsyncResult res) { Socket client = (Socket)res.AsyncState; int size = client.EndReceive(res); if (size > 0) { string address = client.RemoteEndPoint.ToString(); // 获取Client的IP和端口 string stringdata = null; if (ClientManager.IsExist(address, false)) // 握手 { stringdata = Encoding.UTF8.GetString(Bytes, 0, size); ClientManager.SendMsgToClient(client, ServerHelper.ResponseHeader(stringdata)); ClientManager.Open(address); } else { stringdata = ServerHelper.DecodeMsg(Bytes, size); } if (stringdata.IndexOf("exit") > -1) { ClientManager.SendMsgToClientList(address + "已从服务器断开", address); ClientManager.Close(address); Console.WriteLine(address + "已从服务器断开"); Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G")); return; } else { Console.WriteLine(stringdata); Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G")); ClientManager.SendMsgToClientList(stringdata, address); } } // 继续等待 client.BeginReceive(Bytes, 0, Bytes.Length, SocketFlags.None, new AsyncCallback(ReceiveTarget), client); } } // 监听请求 class AcceptHelper { public byte[] Bytes { get; set; } public void AcceptTarget(IAsyncResult res) { Socket server = (Socket)res.AsyncState; Socket client = server.EndAccept(res); string address = client.RemoteEndPoint.ToString(); ClientManager.Add(new ClientInfo() { Socket = client, Address = address, IsOpen = false }); ReceiveHelper rs = new ReceiveHelper() { Bytes = this.Bytes }; IAsyncResult recres = client.BeginReceive(rs.Bytes, 0, rs.Bytes.Length, SocketFlags.None, new AsyncCallback(rs.ReceiveTarget), client); // 继续监听 server.BeginAccept(new AsyncCallback(AcceptTarget), server); } } class Program { static void Main(string[] args) { Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200)); // 绑定IP+端口 server.Listen(10); // 开始监听 Console.WriteLine("等待连接..."); AcceptHelper ca = new AcceptHelper() { Bytes = new byte[2048] }; IAsyncResult res = server.BeginAccept(new AsyncCallback(ca.AcceptTarget), server); string str = string.Empty; while (str != "exit") { str = Console.ReadLine(); Console.WriteLine("ME: " + DateTimeOffset.Now.ToString("G")); ClientManager.SendMsgToClientList(str); } ClientManager.Close(); server.Close(); } } }
Client:
<!DOCTYPE html> <script> var mySocket; function Star() { mySocket = new WebSocket("ws://127.0.0.1:200", "my-custom-protocol"); mySocket.onopen = function Open() { Show("连接打开"); }; mySocket.onmessage = function (evt) { Show(evt.data); }; mySocket.onclose = function Close() { Show("连接关闭"); mySocket.close(); }; } function Send() { var content = document.getElementById("content").value; Show(content); mySocket.send(content); } function Show(msg) { var roomContent = document.getElementById("roomContent"); roomContent.innerHTML = msg + "<br/>" + roomContent.innerHTML; } </script> <html> <head> <title></title> </head> <body> <div id="roomContent"> </div> <div> <textarea id="content" cols="50" rows="3"></textarea> </div> <input type="button" value="Connection" οnclick="Star()" /> <input type="button" value="Send" οnclick="Send()" /> </body> </html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- C#用websocket实现简易聊天功能(客户端)
- C#用websocket实现简易聊天功能(服务端)
- C#使用WebSocket实现聊天室功能
- C# 实现WebSocket服务端教程
- C# websocket及时通信协议的实现方法示例
- C#实现WebSocket协议客户端和服务器websocket sharp组件实例解析
- C# Websocket连接实现wss协议
express框架实现基于Websocket建立的简易聊天室
最近想写点有意思的,所以整了个这个简单的不太美观的小玩意
首先你得确认你的电脑装了node,然后就可以按照步骤 搞事情了~~
1.建立一个文件夹
2.清空当前文件夹地址栏,在文件夹地址栏中输入cmd.exe
3.我们需要下载点小东西 ,需要在命令行输入
- npm install express 回车 等待一会
- npm install express-session 回车 等待一会
- npm install ejs 回车 等待一会
- npm install socket.io 回车 等待一会 叮~~~ 搞定!!!
4.安装完成后,在你建的文件夹下 就会有一个 node_modules文件夹,接下来我们还需要建立俩文件夹,一个文件夹(public)存放静态资源,并且添加jquery文件,一个文件夹(views)存放静态模板ejs文件。
5.接下来我们就需要建立一个入口文件(app.js),在你建立的文件夹下 。
6.app.js中必须写的
var express=require(''express''); var app=express(); //加载express web server var http=require(''http'').Server(app); //加载websocket server-->http://localhost:3000/socket.io/socket.io.js var io=require(''socket.io'')(http); //监听端口3000 http.listen(3000);
7.(1)加载路由、处理路由、配置ejs模板、处理静态资源管理器
app.get app.post app.set("view engine","ejs"); app.use(express.static(''./public''));
(2)建立俩文件,index.ejs、chat.ejs,在chat.ejs下我们需要引入
<script src="/socket.io/socket.io.js"></script> <script src="/jquery-1.12.4.js"></script>
如果你本地没有的话,你可以这样玩~~
咱可以引用在线的嘛(亲测好使)
<script src="http://code.jquery.com/jquery-latest.js"></script>
8.app.get 路由 action=‘check''
判断登陆的三个条件
1-不能为空
2-不能重名
3-注册并且跳转chat页面
9.咱登陆了,要聊天,咱得告诉别人咱叫啥啊!!!所以这里需要处理session了,并且在chat页面显示出来嘛
10.所以咱得开始建立websocket通讯了
client
<script src="/socket.io/socket.io.js"></script> <script src="/jquery-1.12.4.js"></script> <script> var socket=io(); socke.emit(''事件名'',''数据''); 数据可以是对象(登陆者和内容) </script>
server
io.on(''connection'',function(socket){ socket.on(''事件名'',function(data){ io.emit(''新的事件名'',data); }); });
client
socket.on(''新的事件名'',function(msg){ dom操作 把msg数据渲染给我们的dom结构 })
基本的思路和步骤就是这些
现在一切工作准备就绪,开始码代码
app.js
var express=require(''express''); var app=express(); var http=require(''http'').Server(app); var io=require(''socket.io'')(http); var session=require(''express-session''); app.use(session({ secret: ''keyboard cat'', resave: false, saveUninitialized: true, //cookie: { secure: true } })); //模板引擎 app.set("view engine","ejs"); //静态服务 app.use(express.static(''./public'')); var alluser=[]; //中间件 //显示首页 app.get(''/'',function(req,res,next){ res.render(''index''); }); //确认登录,检查此人是否有用户名 昵称不能重复 app.get(''/check'',function(req,res,next){ var yonghuming=req.query.yonghuming; if(!yonghuming){ res.send(''必须填写用户名''); return; } if(alluser.indexOf(yonghuming) != -1){ res.send(''用户名重名''); return; } alluser.push(yonghuming); console.log(alluser); req.session.yonghuming=yonghuming; res.redirect("/chat"); }); //聊天室 app.get(''/chat'',function(req,res,next){ //console.log(req.session.yonghuming); //console.log(123); if(!req.session.yonghuming){ res.redirect("/"); return; } res.render(''chat'',{ ''yonghuming'':req.session.yonghuming }); }); io.on(''connection'',function(socket){ socket.on(''liaotian'',function(msg){ console.log(msg); //io.emit(''liaotian'',msg); //console.log(io); io.emit(''liaotian'',msg); }); }) //监听端口 http.listen(3000); console.log(''server start port 3000'');
index.ejs(放views文件夹下)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> div{ width:700px; height:30px; padding:40px; border:1px solid #000; margin:0 auto; } #yonghuming{ font-size:30px; } </style> </head> <body> <div> <form action="/check" method="get"> 输入昵称: <input type="text" id="yonghuming" name="yonghuming"> <input type="submit" value="进入聊天室"> </form> </div> </body> </html>
chat.ejs
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Document</title> <style> .caozuo{ position:fixed; bottom:0; left:0; height:100px; background-color:#eee; width:100%; } .caozuo input{ font-size:30px; } .caozuo input[type=text]{ width:100%; } </style> </head> <body> <h1>Edison聊天室<span id="yonghu"> 欢迎:<%=yonghuming %></span></h1> <div> <ul></ul> </div> <div> <input type="text" id="neirong"/> <input type="button" id="fayan" value="发言"/> </div> <script src="/socket.io/socket.io.js"></script> <script src="/jquery-1.12.4.min.js"></script> <script> var socket=io(); $(''#neirong'').keydown(function(e){ if(e.keyCode==13){ //回车发送消息 socket.emit(''liaotian'',{ ''neirong'':$(''#neirong'').val(), ''ren'':$(''#yonghu'').html(), }); $(this).val(''''); } }); /* $("#fayan").click(function(){ //点击发言按钮发送消息 socket.emit(''liaotian'',{ ''neirong'':$(''#neirong'').val(), ''ren'':$(''#yonghu'').html(), }); });*/ socket.on(''liaotian'',function(msg){ $(".liebiao").prepend("<li><b>"+msg.ren+": </b>"+msg.neirong+"</li>"); }); </script> </body> </html>
聊天室登陆界面
edison进入聊天室
edison与chan聊天
在码代码过程中,不断的踩坑,填坑,第一次整这玩意,很多地方不熟悉,难免有些错误,毕竟学习过程嘛,有点磕碜,如果你们也写了好使了,咱可以共同进步一起美化,完善更多的功能,忘各位old铁见谅~~~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- node.js基于express使用websocket的方法
- express中创建 websocket 接口及问题解答
关于Golang实现基于Websocket协议的H5聊天室和golang websocket的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于.NET Core 基于Websocket的在线聊天室、.NET Core 基于Websocket的在线聊天室实现、C#基于WebSocket实现聊天室功能、express框架实现基于Websocket建立的简易聊天室等相关知识的信息别忘了在本站进行查找喔。
本文标签: