本文实例为大家分享了c#基于websocket实现聊天室功能的具体代码,供大家参考,具体内容如下
前面两篇温习了,c# socket内容
本章根据socket异步聊天室修改成websocket聊天室
websocket特别的地方是 握手和消息内容的编码、解码(添加了rverhelper协助处理)
rverhelper:
using system;using system.collections;using system.text;using system.curity.cryptography;namespace socketdemo{ // rver助手 负责:1 握手 2 请求转换 3 响应转换 class rverhelper { /// <summary> /// 输出连接头信息 /// </summary> public static string responheader(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("c-websocket-origin") ? table["c-websocket-origin"].tostring() : string.empty); header.appendformat("websocket-location: {0}\r\n", table.containskey("host") ? table["host"].tostring() : string.empty); string key = table.containskey("c-websocket-key") ? table["c-websocket-key"].tostring() : string.empty; string magic = "258eafa5-e914-47da-95ca-c5ab0dc85b11"; header.appendformat("c-websocket-accept: {0}\r\n", convert.toba64string(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) != x趋近于00x80) { 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; } el 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.getstri意识形态是什么ng(buffer,期望英文 beginindex, payload_len); } /// <summary> /// 编码响应内容 /// </summar包涵y> 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); } el 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); } el { byte[] st = system.text.encoding.utf8.getbytes(string.format("暂不处理超长内容").tochararray()); } return bts; } }}
rver:
using system;using system.collections.generic;using system.text;using system.net;using system.net.sockets;namespace socketdemo{ class clientinfo { public socket socket { get; t; } public bool isopen { get; t; } public string address { get; t; } } // 管理client class clientmanager { static list<clientinfo> clientlist = new list<clientinfo>(); public static void add(clientinfo info) { if (!ixist(info.address)) { clientlist.add(info); } } public static bool ixist(string address) { return clientlist.exists(item => string.compare(address, item.address, true) == 0); } public static bool ixist(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 clo(string address = null) { clientlist.foreach(item => { if (address == null || string.compare(address, item.address, true) == 0) { item.isopen = fal; item.socket.shutdown(socketshutdown.both); } }); } // 发送消息到clientlist public static void ndmsgtoclientlist(string msg, string address = null) { clientlist.foreach(item => { if (item.isopen && (address == null || item.address != address)) { ndmsgtoclient(item.socket, msg); } }); } public static void ndmsgtoclient(socket client, string msg) { byte[] bt = rverhelper.encodemsg(msg); client.beginnd(bt, 0, bt.length, socketflags.none, new asynccallback(ndtarget), client); } private static void ndtarget(iasyncresult res) { //socket client = (socket)res.asyncstate; //int size = client.endnd(res); } } // 接收消息 class receivehelper { public byte[] bytes { get; t; } 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.ixist(address, fal)) // 握手 { stringdata = encoding.utf8.getstring(bytes, 0, size); clientmanager.ndmsgtoclient(client, rverhelper.responheader(stringdata)); clientmanager.open(address); } el { stringdata = rverhelper.decodemsg(bytes, size); } if (stringdata.indexof("exit") > -1) { clientmanager.ndmsgtoclientlist(address + "已从服务器断开", address); clientmanager.clo(address); console.writeline(address + "已从服务器断开"); console.writeline(address + " " + datetimeofft.now.tostring("g")); return; } el { console.writeline(stringdata); console.writeline(address + " " + datetimeofft.now.tostring("g")); clientmanager.ndmsgtoclientlist(stringdata, address); } } // 继续等待 client.beginreceive(bytes, 0, bytes.length, socketflags.none, new asynccallback(receivetarget), client); } } // 监听请求 class accepthelper { public byte[] bytes { get; t; } public void accepttarget(iasyncresult res) { socket rver = (socket)res.asyncstate; socket client = rver.endaccept(res); string address = client.remoteendpoint.tostring(); clientmanager.add(new clientinfo() { socket = client, address = address, isopen = fal }); receivehelper rs = new receivehelper() { bytes = this.bytes }; iasyncresult recres = client.beginreceive(rs.bytes, 0, rs.bytes.length, socketflags.none, new asynccallback(rs.receivetarget), client); // 继续监听 rver.beginaccept(new asynccallback(accepttarget), rver); } } class program { static void main(string[] args) { socket rver = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); rver.bind(new ipendpoint(ipaddress.par("127.0.0.1"), 200)); // 绑定ip+端口 rver.listen(10); // 开始监听 console.writeline("等待连接..."); accepthelper ca = new accepthelper() { bytes = new byte[2048] }; iasyncresult res = rver.beginaccept(new asynccallback(ca.accepttarget), rver); string str = string.empty; while (str != "exit") { str = console.readline(); console.writeline("me: " + datetimeofft.now.tostring("g")); clientmanager.ndmsgtoclientlist(str); } clientmanager.clo(); rver.clo(); } }}
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.onclo = function clo() { show("连接关闭"); mysocket.clo(); }; } function nd() { var content = document.getelementbyid("content").value; show(content); mysocket.nd(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" style="width: 500px; height: 200px; overflow: hidden; border: 2px solid #686868; margin-bottom: 10px; padding: 10px 0px 0px 10px;"> </div> <div> <textarea id=江苏省常州高级中学"content" cols="50" rows="3" style="padding: 10px 0px 0px 10px;"></textarea> </div> <input type="button" value="connection" οnclick="star()" /> <input type="button" value="nd" οnclick="nd()" /></body></html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。
本文发布于:2023-04-05 00:08:00,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/81ad00ecd32142fe49a19c137bd96a37.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:C#基于WebSocket实现聊天室功能.doc
本文 PDF 下载地址:C#基于WebSocket实现聊天室功能.pdf
留言与评论(共有 0 条评论) |