C# Socket服务器及多客户端连接示例
程序员文章站
2022-05-10 19:23:18
服务端代码[控制台示例] Socket 相关类 客户端连接[网页测试]
服务端代码[控制台示例]
static list<socket> sockets = new list<socket>(); static void main(string[] args) { int port = 10; byte[] buffer = new byte[1024]; ipendpoint localep = new ipendpoint(ipaddress.any, port); socket listener = new socket(localep.address.addressfamily, sockettype.stream, protocoltype.tcp); try { listener.bind(localep); listener.listen(10); console.writeline("等待客户端连接...."); while (true) //该操作用于多个客户端连接 { socket sc = listener.accept();//接受一个连接 sockets.add(sc); //将连接的客户端, 添加到内存当中 thread t = new thread(new threadstart(() => receivedata(sc))); //开启当前socket线程, 去执行获取数据的动作,与客户端通信 t.isbackground = true; t.start(); } } catch (exception e) { console.writeline(e.tostring()); } console.readline(); } public static void receivedata(socket sc) { byte[] buffer = new byte[1024]; console.writeline("接受到了客户端:" + sc.remoteendpoint.tostring() + "连接...."); //握手 int length = sc.receive(buffer);//接受客户端握手信息 sc.send(packhandshakedata(getseckeyaccetp(buffer, length)));while (true) { try { //接受客户端数据 console.writeline("等待客户端数据...."); length = sc.receive(buffer);//接受客户端信息 string clientmsg = analyticdata(buffer, length); console.writeline("接受到客户端数据:" + clientmsg); //发送数据 string sendmsg = "服务端返回信息:" + clientmsg; sc.send(packdata(sendmsg)); } catch (exception ex) { sockets.remove(sc); //如果接收的过程中,断开, 那么内存中移除当前socket对象, 并且退出当前线程 console.writeline("客户端已经断开连接!"); return; } } }
socket 相关类
/// <summary> /// 打包握手信息 /// </summary> /// <param name="seckeyaccept"></param> /// <returns></returns> private static byte[] packhandshakedata(string seckeyaccept) { var responsebuilder = new stringbuilder(); responsebuilder.append("http/1.1 101 switching protocols" + environment.newline); responsebuilder.append("upgrade: websocket" + environment.newline); responsebuilder.append("connection: upgrade" + environment.newline); responsebuilder.append("sec-websocket-accept: " + seckeyaccept + environment.newline + environment.newline); return encoding.utf8.getbytes(responsebuilder.tostring()); } /// <summary> /// 生成sec-websocket-accept /// </summary> /// <param name="handshaketext">客户端握手信息</param> /// <returns>sec-websocket-accept</returns> private static string getseckeyaccetp(byte[] handshakebytes, int byteslength) { string handshaketext = encoding.utf8.getstring(handshakebytes, 0, byteslength); string key = string.empty; regex r = new regex(@"sec\-websocket\-key:(.*?)\r\n"); match m = r.match(handshaketext); if (m.groups.count != 0) { key = regex.replace(m.value, @"sec\-websocket\-key:(.*?)\r\n", "$1").trim(); } byte[] encryptionstring = sha1.create().computehash(encoding.ascii.getbytes(key + "258eafa5-e914-47da-95ca-c5ab0dc85b11")); return convert.tobase64string(encryptionstring); } /// <summary> /// 解析客户端数据包 /// </summary> /// <param name="recbytes">服务器接收的数据包</param> /// <param name="recbytelength">有效数据长度</param> /// <returns></returns> private static string analyticdata(byte[] recbytes, int recbytelength) { if (recbytelength < 2) { return string.empty; } bool fin = (recbytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧 if (!fin) { return string.empty;// 超过一帧暂不处理 } bool mask_flag = (recbytes[1] & 0x80) == 0x80; // 是否包含掩码 if (!mask_flag) { return string.empty;// 不包含掩码的暂不处理 } int payload_len = recbytes[1] & 0x7f; // 数据长度 byte[] masks = new byte[4]; byte[] payload_data; if (payload_len == 126) { array.copy(recbytes, 4, masks, 0, 4); payload_len = (uint16)(recbytes[2] << 8 | recbytes[3]); payload_data = new byte[payload_len]; array.copy(recbytes, 8, payload_data, 0, payload_len); } else if (payload_len == 127) { array.copy(recbytes, 10, masks, 0, 4); byte[] uint64bytes = new byte[8]; for (int i = 0; i < 8; i++) { uint64bytes[i] = recbytes[9 - i]; } uint64 len = bitconverter.touint64(uint64bytes, 0); payload_data = new byte[len]; for (uint64 i = 0; i < len; i++) { payload_data[i] = recbytes[i + 14]; } } else { array.copy(recbytes, 2, masks, 0, 4); payload_data = new byte[payload_len]; array.copy(recbytes, 6, payload_data, 0, payload_len); } for (var i = 0; i < payload_len; i++) { payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]); } return encoding.utf8.getstring(payload_data); } /// <summary> /// 打包服务器数据 /// </summary> /// <param name="message">数据</param> /// <returns>数据包</returns> private static byte[] packdata(string message) { byte[] contentbytes = null; byte[] temp = encoding.utf8.getbytes(message); if (temp.length < 126) { contentbytes = new byte[temp.length + 2]; contentbytes[0] = 0x81; contentbytes[1] = (byte)temp.length; array.copy(temp, 0, contentbytes, 2, temp.length); } else if (temp.length < 0xffff) { contentbytes = new byte[temp.length + 4]; contentbytes[0] = 0x81; contentbytes[1] = 126; contentbytes[2] = (byte)(temp.length & 0xff); contentbytes[3] = (byte)(temp.length >> 8 & 0xff); array.copy(temp, 0, contentbytes, 4, temp.length); } else { // 暂不处理超长内容 } return contentbytes; }
客户端连接[网页测试]
<!doctype html>
websockets客户端示例 websocket客户端示例
请输入一些文字
<!doctype html> <html> <head> <meta charset="utf-8" /> <title>websockets客户端示例</title> </head> <script> var websocket; function connect() { try { var readystate = new array("正在连接","已建立连接","正在关闭连接","已关闭连接"); var host = "ws://localhost:10"; websocket = new websocket(host); var message = document.getelementbyid("message"); message.innerhtml +="<p>socket状态:" + readystate[websocket.readystate] + "</p>"; websocket.onopen = function() { message.innerhtml += "<p>socket状态:" + readystate[websocket.readystate] + "</p>"; } websocket.onmessage = function(msg) { message.innerhtml +="<p>接收信息:" + msg.data + "</p>"; } websocket.onclose=function() { message.innerhtml +="<p>socket状态:" + readystate[websocket.readystate] + "</p>"; } } catch(exception) { message.innerhtml += "<p>有错误发生</p>"; } } function send() { var text = document.getelementbyid("text").value; var message = document.getelementbyid("message"); if(text == "") { message.innerhtml += "<p>请输入一些文字</p>"; return ; } try { websocket.send(text); message.innerhtml += "<p>发送数据:" +text + "</p>"; } catch(exception) { message.innerhtml += "<p>发送数据出错</p>"; } document.getelementbyid("text").value=""; } function disconnect() { websocket.close(); } </script> <body> <h1>websocket客户端示例</h1> <div id="message"></div> <p>请输入一些文字</p> <input id="text" type="text"> <button id="connect" onclick="connect();">建立连接</button> <button id="send" onclick="send();">发送数据</button> <button id="disconnect" onclick="disconnect();">断开连接</button> </body> </html>
上一篇: 鹅蛋营养价值以及功效,这些你都了解么?
下一篇: 查找和排序:旋转数组的最小数字