先看看测试结果:
服务端:
服务器端控制台:
可以发现我服务端连了2个客户端,第一个为局域网的一台机器,另一个为服务器的主机
ip为192.168.1.105 ,端口为42794的客户端:
ip为192.168.1.104,端口为30547的客户端:
需要发送聊天信息 : 使用“chat:”作为前缀。
值得注意的是 : 本文只探讨异步Socket的封装 , 包括包头和包 。对与体验效果不好,不是此次讨论的范围,Sorry。
一,核心 :
①:关于消息的构建类库:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SocketTool { public sealed class SocketMsgTool { /// <summary> /// 构造一个发送包 /// </summary> /// <param name="mainCode">主码</param> /// <param name="subCode">分码</param> /// <param name="type">类型码</param> /// <param name="Body">包体</param> /// <returns></returns> public static byte[] Creat_Msg(ushort mainCode, ushort subCode, ushort type, byte[] Body) { List<byte> cur = new List<byte>(Body); cur.InsertRange(0, BitConverter.GetBytes(mainCode)); cur.InsertRange(2, BitConverter.GetBytes(subCode)); cur.InsertRange(4, BitConverter.GetBytes(type)); ushort body_len = Convert.ToUInt16(Body.Length); cur.InsertRange(6, BitConverter.GetBytes(body_len)); return cur.ToArray<byte>(); } /// <summary> /// 获取主码 /// </summary> /// <param name="msg"></param> /// <returns></returns> public static ushort Get_MainCode(byte[] msg) { return BitConverter.ToUInt16(msg, 0); } /// <summary> /// 获取分码 /// </summary> /// <param name="msg"></param> /// <returns></returns> public static ushort Get_SubCode(byte[] msg) { return BitConverter.ToUInt16(msg, 2); } /// <summary> /// 获取类型码 /// </summary> /// <param name="msg"></param> /// <returns></returns> public static ushort Get_Type(byte[] msg) { return BitConverter.ToUInt16(msg, 4); } /// <summary> /// 获取包体 /// </summary> /// <param name="msg"></param> /// <returns></returns> public static byte[] Get_Body(byte[] msg) { byte[] body = new byte[BitConverter.ToUInt16(msg, 6)]; Array.Copy(msg, 8, body, 0, body.Length); return body; } } }
②关于字节数组方法的扩展:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Async_Svr_Socket_Lib.com { /// <summary> /// 字节数组(byte[])的方法扩展 /// </summary> internal static class ByteArr_Fun_Extends { /// <summary> /// 追加数据到Buffer /// </summary> /// <param name="buffer"></param> /// <param name="buffer_off_index">数据的偏移下标</param> /// <param name="add">增加的byte[]</param> /// <returns>需要增加的size量</returns> public static int Push_Data(this byte[] buffer, ref int buffer_off_index, byte[] add) { int cur_con_count = buffer.Length - ( buffer_off_index + 1 ); if (add.Length > cur_con_count) { //需要扩大buffer的size int off = add.Length - cur_con_count; Array.Resize<byte>(ref buffer, buffer.Length + off);//扩充buffer的size add.CopyTo(buffer, buffer_off_index + 1); buffer_off_index += add.Length;//更新偏移 return off; } else { //不需要扩大buffer的size add.CopyTo(buffer, buffer_off_index + 1); buffer_off_index += add.Length;//更新偏移 return 0; } } /// <summary> /// 压人新的数据(一般为包头) - 构造新的发送包 /// </summary> /// <param name="buffer_send">需要发送的包体</param> /// <param name="unshift">压入增加的byte[]</param> /// <returns>需要增加的size量</returns> public static void Unshift_Data(this byte[] buffer_send , byte[] unshift) { byte[] effective = buffer_send.Skip<byte>(0).Take<byte>(buffer_send.Length).ToArray<byte>(); List<byte> list = new List<byte>(effective); list.InsertRange(0, unshift);//头部插入 buffer_send = list.ToArray();//重新指定数据 } /// <summary> /// 获取当前数据(取出一个完整的包) /// </summary> /// <param name="buffer"></param> /// <param name="buffer_off_index">数据的偏移下标</param> /// <param name="cur_len">整个包的长度</param> /// <returns>当前的包</returns> public static byte[] Shift_Data(this byte[] buffer, ref int buffer_off_index, int cur_len) { byte[] next_buffer = null; if (cur_len < buffer_off_index + 1) next_buffer = buffer.Skip<byte>(cur_len - 1).Take<byte>(buffer_off_index + 1 - cur_len).ToArray<byte>();//下一个包(存在粘包) byte[] cur_buffer = buffer.Skip<byte>(0).Take<byte>(cur_len).ToArray<byte>();//当前的包(完整) if (next_buffer == null) buffer_off_index = -1; else { Array.Resize<byte>(ref buffer, next_buffer.Length); next_buffer.CopyTo(buffer, 0);//注入新的包 buffer_off_index = next_buffer.Length - 1; } return cur_buffer; } } }
③关于服务端Socket类库:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using Async_Svr_Socket_Lib.com; using System.ComponentModel; namespace Async_Svr_Socket_Lib { /// <summary> /// 服务器Socket封装 /// </summary> public sealed class Svr_Socket { private Socket _listener = null;//服务器Socket private readonly IPEndPoint _ip_point = null; private Action<Socket_CallBack_Type, Object, Socket> _callback = null;//回调函数 private readonly int _connect_count = 0; private readonly int _state_object_bufferlen = 0; private ManualResetEvent allDone = null;//信号量 private Timer _heart_beat_timer = null;//心跳包及时机制 /// <summary> /// 构造函数 /// </summary> /// <param name="ip_point">服务端ip+port</param> /// <param name="callback">回调函数</param> /// <param name="connect_count">可连接的服务端个数</param> /// <param name="state_object_bufferlen">client buffer长度</param> public Svr_Socket(IPEndPoint ip_point, Action<Socket_CallBack_Type, Object, Socket> callback, int connect_count = 100, int state_object_bufferlen = 512) { this._ip_point = ip_point; this._callback = callback; this._connect_count = connect_count; this._state_object_bufferlen = state_object_bufferlen; } /// <summary> /// 请求连接Socket服务器 /// </summary> public void Accept() { this._listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//构建Tcp通讯 allDone = new ManualResetEvent(false); try { this._listener.Bind(this._ip_point); this._listener.Listen(this._connect_count); while (true)//持续的监听连接 { allDone.Reset();//置为无信号状态 this._listener.BeginAccept(new AsyncCallback(this.Async_Accept_Callback), this._listener); allDone.WaitOne();//当前线程等待 } } catch (Exception e) { Console.WriteLine("Socket Error! -> {0}" , e.Message); } } //连接异步回调处理 private void Async_Accept_Callback(IAsyncResult ar) { allDone.Set();//置为有信号状态 Socket listener = (Socket)ar.AsyncState; try { Socket client = listener.EndAccept(ar); State_Object state = new State_Object(this._state_object_bufferlen); state.Client_Socket = client; this._callback(Socket_CallBack_Type.connect_succ, true, client);//连接成功 this.receive(state); } catch (Exception e) { this._callback(Socket_CallBack_Type.connect_fail, e, null); } } //接收字节 private void receive(State_Object state) { state.Client_Socket.BeginReceive(state.Buffer, state.Buffer_Off_Index + 1, state.Buffer.Length - (state.Buffer_Off_Index + 1), 0, new AsyncCallback(this.Async_Receive_Callback), state); } //接收异步回调处理 private void Async_Receive_Callback(IAsyncResult ar) { State_Object state = (State_Object)ar.AsyncState; try { int byte_read_count = state.Client_Socket.EndReceive(ar);//接收的字节数 if (byte_read_count > 0) { state.Buffer_Off_Index += byte_read_count; this.Receive_Handler(state); } else { //玩家主动关闭了连接 this._callback(Socket_CallBack_Type.client_active_off, null, state.Client_Socket); } } catch( Exception e ) { //玩家被迫断开(客户端没发送断开指令) this._callback(Socket_CallBack_Type.client_passive_off, e, state.Client_Socket); } } /// <summary> /// 处理了粘包及断包 /// </summary> /// <param name="state"></param> private void Receive_Handler(State_Object state ) { byte[] client_buffer = state.Buffer; if (state.Buffer_Off_Index + 1 >= 8)//如果包头取到 { ushort body_len = BitConverter.ToUInt16(state.Buffer, 6); ushort packet_all_len = Convert.ToUInt16(body_len + 8); if (packet_all_len <= state.Buffer_Off_Index + 1) { int buffer_off_index = state.Buffer_Off_Index; byte[] cur_packet = state.Buffer.Shift_Data(ref buffer_off_index, packet_all_len);//取出当前的包(一整个包) state.Buffer_Off_Index = buffer_off_index;//重新赋值 this._callback( Socket_CallBack_Type.receive, cur_packet, state.Client_Socket);//回调接收到的包 if (state.Buffer_Off_Index == -1) { Array.Resize<byte>(ref client_buffer, this._state_object_bufferlen);//再次初始化buffer this.receive(state); } else { this.Receive_Handler(state); } } else if (packet_all_len > state.Buffer.Length)//当包长大于buffer时 { Array.Resize<byte>(ref client_buffer, state.Buffer.Length + this._state_object_bufferlen); this.receive(state); } else { this.receive(state); } } else { this.receive(state); } } /// <summary> /// 发送信息 /// </summary> /// <param name="socket"></param> /// <param name="msg">要发送的信息</param> public void Send(Socket socket, byte[] msg) { if (socket != null && socket.Connected) { socket.BeginSend(msg, 0, msg.Length, 0, new AsyncCallback(this.Async_Send_Callback), socket); } } //发送信息返回 private void Async_Send_Callback(IAsyncResult ar) { Socket socket = (Socket)ar.AsyncState; int byte_send_count = socket.EndSend(ar); this._callback(Socket_CallBack_Type.send, byte_send_count, socket); } } /// <summary> /// Socket回调类型 /// </summary> public enum Socket_CallBack_Type : uint { [Description("连接成功")] connect_succ = 0, [Description("连接失败")] connect_fail = 1, [Description("接收返回")] receive = 2, [Description("发送返回")] send = 3, [Description("客户端被迫断开")] client_passive_off = 4, [Description("客户端主动断开")] client_active_off = 5 } }
④关于客户端Socket类库:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using Async_Cli_Socket_Lib.com; using System.ComponentModel; namespace Async_Cli_Socket_Lib { /// <summary> /// 客户端socket /// </summary> public sealed class Cli_Socket { private Socket _client = null; private IPEndPoint _ip_point = null; private Action<Socket_CallBack_Type , Object> _callback = null; private readonly int _state_object_bufferlen = 0; private State_Object _state = null; /// <summary> /// /// </summary> /// <param name="ip_point">服务端ip+port</param> /// <param name="callback">回调函数</param> /// <param name="state_object_bufferlen">buffer默认size</param> public Cli_Socket(IPEndPoint ip_point, Action<Socket_CallBack_Type, Object> callback, int state_object_bufferlen = 512) { this._ip_point = ip_point; this._callback = callback; this._state_object_bufferlen = state_object_bufferlen; this._state = new State_Object(state_object_bufferlen); } /// <summary> /// 获取Socket /// </summary> public Socket Client { get { return this._client; } } public void Connect() { if (_client == null) _client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _client.BeginConnect(this._ip_point, new AsyncCallback(this.Async_Connect_Callback), _client); } private void Async_Connect_Callback(IAsyncResult ar) { Socket client = (Socket)ar.AsyncState; try { client.EndConnect(ar); this._callback(Socket_CallBack_Type.connect_succ, true); this.receive();//开始接收数据 } catch (Exception e) { this._callback(Socket_CallBack_Type.connect_fail, e); } } //开始接收数据 private void receive() { this._client.BeginReceive(this._state.Buffer, this._state.Buffer_Off_Index + 1, this._state.Buffer.Length - (this._state.Buffer_Off_Index + 1), 0, new AsyncCallback(this.Async_Receive_Callback), this._state); } //接收数据返回 private void Async_Receive_Callback(IAsyncResult ar) { State_Object state = (State_Object)ar.AsyncState; try { int byte_read_count = this._client.EndReceive(ar);//接收的字节数 if (byte_read_count > 0) { state.Buffer_Off_Index += byte_read_count;//增加的数据量 this.Receive_Handler(state); } else { this._callback(Socket_CallBack_Type.server_active_off, this._client); } } catch (Exception e) { this._callback(Socket_CallBack_Type.server_passive_off, e); } } private void Receive_Handler(State_Object state) { byte[] client_buffer = state.Buffer; if (state.Buffer_Off_Index + 1 >= 8)//包头的信心已经收到 { ushort body_len = BitConverter.ToUInt16(state.Buffer, 6); ushort packet_all_len = Convert.ToUInt16(body_len + 8); if (packet_all_len <= state.Buffer_Off_Index + 1) { int buffer_off_index = state.Buffer_Off_Index; byte[] cur_packet = state.Buffer.Shift_Data(ref buffer_off_index, packet_all_len);//取出当前的包(一整个包) state.Buffer_Off_Index = buffer_off_index;//重新赋值 this._callback(Socket_CallBack_Type.receive ,cur_packet);//回调接收到的包------------------ if (state.Buffer_Off_Index == -1) { Array.Resize<byte>(ref client_buffer, this._state_object_bufferlen);//再次初始化buffer this.receive(); } else { this.Receive_Handler(state); } } else if (packet_all_len > state.Buffer.Length) { Array.Resize<byte>(ref client_buffer, state.Buffer.Length + this._state_object_bufferlen); this.receive(); } else { this.receive(); } } else { this.receive(); } } /// <summary> /// 发送Socket请求 /// </summary> /// <param name="msg">请求信息</param> public void Send(byte[] msg) { _client.BeginSend(msg, 0, msg.Length, 0, new AsyncCallback(this.Async_Send_Callback), this._state); } private void Async_Send_Callback(IAsyncResult ar) { State_Object state = (State_Object)ar.AsyncState; int byte_send_count = this._client.EndSend(ar);//发送了多少字节 this._callback(Socket_CallBack_Type.send, byte_send_count); } } /// <summary> /// Socket回调类型 /// </summary> public enum Socket_CallBack_Type : uint { [Description("连接成功")] connect_succ = 0, [Description("连接失败")] connect_fail = 1, [Description("接收返回")] receive = 2, [Description("发送返回")] send = 3, [Description("服务端被迫断开")] server_passive_off = 4, [Description("服务端主动断开")] server_active_off = 5 } }
⑤:服务端 state_object
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; namespace Async_Svr_Socket_Lib.com { /// <summary> /// Socket数据 /// </summary> internal sealed class State_Object { /// <summary> /// Client Socket /// </summary> public Socket Client_Socket { set; get; } private byte[] _buffer = null; private int _buffer_off_index = -1; /// <summary> /// 构造函数 /// </summary> /// <param name="buffer_size">缓存初始的字节数</param> public State_Object(int buffer_size = 512) { this._buffer = new byte[buffer_size]; this.Buffer_Off_Index = -1; } /// <summary> /// 字节数组 /// </summary> public byte[] Buffer { get { return this._buffer; } } /// <summary> /// 缓存已经存储的下标( 显然从0开始 , -1表示没有数据 ) /// </summary> public int Buffer_Off_Index { set { this._buffer_off_index = value; } get { return this._buffer_off_index; } } } }
⑥:客户端state_object
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Async_Cli_Socket_Lib.com { /// <summary> /// Socket数据 /// </summary> internal sealed class State_Object { private byte[] _buffer = null; private int _buffer_off_index = -1; /// <summary> /// 构造函数 /// </summary> /// <param name="buffer_size">缓存初始的字节数</param> public State_Object(int buffer_size = 512) { this._buffer = new byte[buffer_size]; this.Buffer_Off_Index = -1; } /// <summary> /// 字节数组 /// </summary> public byte[] Buffer { get { return this._buffer; } } /// <summary> /// 缓存已经存储的下标( 显然从0开始 , -1表示没有数据 ) /// </summary> public int Buffer_Off_Index { set { this._buffer_off_index = value; } get { return this._buffer_off_index; } } } }
二,测试(使用控制台)
①:服务端
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Async_Svr_Socket_Lib; using System.Net; using System.Net.Sockets; using SocketTool; using System.Diagnostics; using System.Threading; namespace Server_Socket_Test { class Program { private Dictionary<string,Socket> _client_list = null;//因为测试的环境原因 , 使用 key :姓名 , 在真实的开发中应该使用用户的ID号 private Svr_Socket _socket = null;//本人封装的服务端Socket static void Main(string[] args) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Green; Thread.CurrentThread.IsBackground = true;//退出后自动杀死进程 IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("192.168.1.104"), 6065); Program pro = new Program(); pro._socket = new Svr_Socket(ipe, pro.CallBack); Console.WriteLine("等待请求连接......."); pro._socket.Accept(); Console.Read(); } private void CallBack(Socket_CallBack_Type type , object msg, Socket client) { string key = String.Empty; switch (type) { case Socket_CallBack_Type.connect_succ: this.connect(msg , client); break; case Socket_CallBack_Type.connect_fail: Console.WriteLine("连接失败 : {0}", ((Exception)msg).Message); break; case Socket_CallBack_Type.receive: this.receive(msg, client); break; case Socket_CallBack_Type.send: //Console.WriteLine("发送的字节数 : {0}", Convert.ToInt32(msg)); break; case Socket_CallBack_Type.client_active_off://主动下线 #if DEBUG Console.WriteLine("{0} 下线了 !!", client.RemoteEndPoint); #endif this.RemoveClient(client); break; case Socket_CallBack_Type.client_passive_off://被迫下线 #if DEBUG Console.WriteLine("{0} 下线了 !!", client.RemoteEndPoint); #endif this.RemoveClient(client); break; } } /// <summary> /// 玩家下线 /// </summary> /// <param name="client"></param> private void RemoveClient(Socket client) { if (this._client_list == null) return; string remove_name = string.Empty; foreach (KeyValuePair<string, Socket> kv in this._client_list) { if (kv.Value == client) { remove_name = kv.Key; break; } } this._client_list.Remove(remove_name); if (client != null && client.Connected) { client.Shutdown(SocketShutdown.Both); client.Close(); } if (this._client_list.Count > 0) { string remove_msg = "{0},下线了!!!"; byte[] msg = Encoding.UTF8.GetBytes(string.Format(remove_msg, remove_name)); msg = SocketMsgTool.Creat_Msg(1, 1, 3, msg); foreach (KeyValuePair<string, Socket> kv in this._client_list) { kv.Value.Send(msg); } } } /// <summary> /// 玩家上线 /// </summary> /// <param name="body"></param> /// <param name="client"></param> private void AddClient( byte[] body , Socket client) { string str = Encoding.UTF8.GetString(body); string name = str.Split(new char[] { ',' })[0]; Console.WriteLine("{0} > {1}", client.RemoteEndPoint, str); //开始启动服务端的心跳包 if (this._client_list == null) this._client_list = new Dictionary<string, Socket>(); if (!this._client_list.ContainsKey(name)) this._client_list.Add(name, client); string add_msg = "{0},上线了!!!"; byte[] msg = Encoding.UTF8.GetBytes(string.Format(add_msg, name)); msg = SocketMsgTool.Creat_Msg(1, 1, 4, msg); foreach (KeyValuePair<string, Socket> kv in this._client_list) { kv.Value.Send(msg); } } private void connect(object msg , Socket client) { Console.WriteLine("连接成功 client ip : {0}" , client.RemoteEndPoint); byte[] welcome = Encoding.UTF8.GetBytes(String.Format("欢迎 : {0} , 尊姓大名?", client.RemoteEndPoint)); welcome = SocketMsgTool.Creat_Msg(1, 1, 1, welcome); client.Send(welcome); } private void receive(object msg, Socket client) { byte[] data = (byte[])msg; ushort mainCode = SocketMsgTool.Get_MainCode(data); ushort subCode = SocketMsgTool.Get_SubCode(data); ushort type = SocketMsgTool.Get_Type(data); byte[] body = SocketMsgTool.Get_Body(data); switch (mainCode) { case 1: switch (subCode) { case 0:// break; case 1: switch (type) { case 2: this.AddClient(body, client); break; } break; } break; case 2: switch (subCode) { case 1: switch (type) { case 1://聊天信息 this.Chat(body, client); break; } break; } break; } } /// <summary> /// 聊天处理 /// </summary> /// <param name="body"></param> /// <param name="client"></param> private void Chat(byte[] body, Socket client) { string msg = Encoding.UTF8.GetString(body); byte[] all_mag = SocketMsgTool.Creat_Msg(2, 1, 1, body); foreach (KeyValuePair<string, Socket> kv in this._client_list) { if (kv.Value != client) { kv.Value.Send(all_mag);//发送聊天信息 } } Console.WriteLine(msg); } } }
②,客户端
using System; using System.Text; using System.Net; using Async_Cli_Socket_Lib; using SocketTool; using System.Net.Sockets; using System.Threading; namespace Client_Socket_Test { class Program { private Cli_Socket _socket = null; private readonly string _name = string.Empty; public Program(string name) { this._name = name; } static void Main(string[] args) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Green; Thread.CurrentThread.IsBackground = true;//退出后自动杀死进程 Console.Write("请输入用户名:"); string name = Console.ReadLine(); IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("192.168.1.104"), 6065); Program pro = new Program(name); pro._socket = new Cli_Socket(ipe, pro.CallBack); Console.WriteLine("请求连接Socket服务器"); pro._socket.Connect(); string code = Console.ReadLine(); while(true) { if (code.Trim().ToLower() == "off") { pro._socket.Client.Shutdown(SocketShutdown.Both); pro._socket.Client.Close(); break; } else { //聊天信息 if (code.Trim() != string.Empty && code.Trim().Substring(0,5) == "chat:") { pro.Chat(code.Trim().Substring(5));//发送聊天信息 } code = Console.ReadLine(); } } } /// <summary> /// 发送聊天信息 /// </summary> /// <param name="msg"></param> private void Chat(string chats) { string msg = string.Format("{0} 说 : {1}", _name, chats); byte[] by = SocketMsgTool.Creat_Msg(2,1,1,Encoding.UTF8.GetBytes(msg)); this._socket.Send(by); } private void CallBack( Socket_CallBack_Type type , Object msg ) { switch (type) { case Socket_CallBack_Type.connect_succ: this.connect(msg); break; case Socket_CallBack_Type.connect_fail: Console.WriteLine("连接失败 : {0}", ((Exception)msg).Message); break; case Socket_CallBack_Type.receive: this.receive(msg); break; case Socket_CallBack_Type.send: Console.WriteLine("发送的字节数 : {0}", Convert.ToInt32(msg)); break; case Socket_CallBack_Type.server_active_off: #if DEBUG Console.WriteLine("主动 : 服务器断开连接 : {0}", (msg as Exception).Message); #endif if (_socket.Client != null && _socket.Client.Connected) { _socket.Client.Shutdown(SocketShutdown.Both); _socket.Client.Close(); } break; case Socket_CallBack_Type.server_passive_off: #if DEBUG Console.WriteLine("被迫 : 服务器断开连接 : {0}", (msg as Exception).Message); #endif if (_socket.Client != null && _socket.Client.Connected) { _socket.Client.Shutdown(SocketShutdown.Both); _socket.Client.Close(); } break; } } private void connect(object msg) { Console.WriteLine("已经成功连接到了Socket服务器了"); } private void receive(object msg) { byte[] data = (byte[])msg; ushort mainCode = SocketMsgTool.Get_MainCode(data); ushort subCode = SocketMsgTool.Get_SubCode(data); ushort type = SocketMsgTool.Get_Type(data); byte[] body = SocketMsgTool.Get_Body(data); switch (mainCode) { case 1: switch (subCode) { case 1: switch (type) { case 0: break; case 1: //Console.WriteLine(Encoding.UTF8.GetString(body)); byte[] hello = Encoding.UTF8.GetBytes(string.Format("{0},请多指教" , this._name)); Console.WriteLine("{0},请多指教", this._name); hello = SocketMsgTool.Creat_Msg(1, 1, 2, hello); this._socket.Send(hello); break; case 3://有玩家下线 string remove_news = string.Format("【{0}】:{1}", "Server", Encoding.UTF8.GetString(body)); Console.WriteLine(remove_news); break; case 4://有玩家上线 string add_msg = Encoding.UTF8.GetString(body); string add_name = add_msg.Split(new char[] { ',' })[0]; if (add_name != _name) { add_msg = string.Format("【{0}】:{1}", "Server", add_msg); Console.WriteLine(add_msg); } break; } break; } break; case 2: switch (subCode) { case 1: switch (type) { case 1://聊天信息 //Console.Clear(); string chat = Encoding.UTF8.GetString(body); Console.WriteLine(chat); break; } break; } break; } } } }
值得注意的是 : 此封装不仅可以用于聊天,body也可以进行加密,用于游戏Socket通讯。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。