您好,登錄后才能下訂單哦!
先看看測(cè)試結(jié)果:
服務(wù)端:
服務(wù)器端控制臺(tái):
可以發(fā)現(xiàn)我服務(wù)端連了2個(gè)客戶端,第一個(gè)為局域網(wǎng)的一臺(tái)機(jī)器,另一個(gè)為服務(wù)器的主機(jī)
ip為192.168.1.105 ,端口為42794的客戶端:
ip為192.168.1.104,端口為30547的客戶端:
需要發(fā)送聊天信息 : 使用“chat:”作為前綴。
值得注意的是 : 本文只探討異步Socket的封裝 , 包括包頭和包 。對(duì)與體驗(yàn)效果不好,不是此次討論的范圍,Sorry。
一,核心 :
①:關(guān)于消息的構(gòu)建類庫(kù):
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SocketTool { public sealed class SocketMsgTool { /// <summary> /// 構(gòu)造一個(gè)發(fā)送包 /// </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; } } }
②關(guān)于字節(jié)數(shù)組方法的擴(kuò)展:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Async_Svr_Socket_Lib.com { /// <summary> /// 字節(jié)數(shù)組(byte[])的方法擴(kuò)展 /// </summary> internal static class ByteArr_Fun_Extends { /// <summary> /// 追加數(shù)據(jù)到Buffer /// </summary> /// <param name="buffer"></param> /// <param name="buffer_off_index">數(shù)據(jù)的偏移下標(biāo)</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) { //需要擴(kuò)大buffer的size int off = add.Length - cur_con_count; Array.Resize<byte>(ref buffer, buffer.Length + off);//擴(kuò)充buffer的size add.CopyTo(buffer, buffer_off_index + 1); buffer_off_index += add.Length;//更新偏移 return off; } else { //不需要擴(kuò)大buffer的size add.CopyTo(buffer, buffer_off_index + 1); buffer_off_index += add.Length;//更新偏移 return 0; } } /// <summary> /// 壓人新的數(shù)據(jù)(一般為包頭) - 構(gòu)造新的發(fā)送包 /// </summary> /// <param name="buffer_send">需要發(fā)送的包體</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();//重新指定數(shù)據(jù) } /// <summary> /// 獲取當(dāng)前數(shù)據(jù)(取出一個(gè)完整的包) /// </summary> /// <param name="buffer"></param> /// <param name="buffer_off_index">數(shù)據(jù)的偏移下標(biāo)</param> /// <param name="cur_len">整個(gè)包的長(zhǎng)度</param> /// <returns>當(dāng)前的包</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>();//下一個(gè)包(存在粘包) byte[] cur_buffer = buffer.Skip<byte>(0).Take<byte>(cur_len).ToArray<byte>();//當(dāng)前的包(完整) 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; } } }
③關(guān)于服務(wù)端Socket類庫(kù):
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> /// 服務(wù)器Socket封裝 /// </summary> public sealed class Svr_Socket { private Socket _listener = null;//服務(wù)器Socket private readonly IPEndPoint _ip_point = null; private Action<Socket_CallBack_Type, Object, Socket> _callback = null;//回調(diào)函數(shù) private readonly int _connect_count = 0; private readonly int _state_object_bufferlen = 0; private ManualResetEvent allDone = null;//信號(hào)量 private Timer _heart_beat_timer = null;//心跳包及時(shí)機(jī)制 /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="ip_point">服務(wù)端ip+port</param> /// <param name="callback">回調(diào)函數(shù)</param> /// <param name="connect_count">可連接的服務(wù)端個(gè)數(shù)</param> /// <param name="state_object_bufferlen">client buffer長(zhǎng)度</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> /// 請(qǐng)求連接Socket服務(wù)器 /// </summary> public void Accept() { this._listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//構(gòu)建Tcp通訊 allDone = new ManualResetEvent(false); try { this._listener.Bind(this._ip_point); this._listener.Listen(this._connect_count); while (true)//持續(xù)的監(jiān)聽(tīng)連接 { allDone.Reset();//置為無(wú)信號(hào)狀態(tài) this._listener.BeginAccept(new AsyncCallback(this.Async_Accept_Callback), this._listener); allDone.WaitOne();//當(dāng)前線程等待 } } catch (Exception e) { Console.WriteLine("Socket Error! -> {0}" , e.Message); } } //連接異步回調(diào)處理 private void Async_Accept_Callback(IAsyncResult ar) { allDone.Set();//置為有信號(hào)狀態(tài) 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); } } //接收字節(jié) 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); } //接收異步回調(diào)處理 private void Async_Receive_Callback(IAsyncResult ar) { State_Object state = (State_Object)ar.AsyncState; try { int byte_read_count = state.Client_Socket.EndReceive(ar);//接收的字節(jié)數(shù) if (byte_read_count > 0) { state.Buffer_Off_Index += byte_read_count; this.Receive_Handler(state); } else { //玩家主動(dòng)關(guān)閉了連接 this._callback(Socket_CallBack_Type.client_active_off, null, state.Client_Socket); } } catch( Exception e ) { //玩家被迫斷開(kāi)(客戶端沒(méi)發(fā)送斷開(kāi)指令) 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);//取出當(dāng)前的包(一整個(gè)包) state.Buffer_Off_Index = buffer_off_index;//重新賦值 this._callback( Socket_CallBack_Type.receive, cur_packet, state.Client_Socket);//回調(diào)接收到的包 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)//當(dāng)包長(zhǎng)大于buffer時(shí) { 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> /// 發(fā)送信息 /// </summary> /// <param name="socket"></param> /// <param name="msg">要發(fā)送的信息</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); } } //發(fā)送信息返回 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回調(diào)類型 /// </summary> public enum Socket_CallBack_Type : uint { [Description("連接成功")] connect_succ = 0, [Description("連接失敗")] connect_fail = 1, [Description("接收返回")] receive = 2, [Description("發(fā)送返回")] send = 3, [Description("客戶端被迫斷開(kāi)")] client_passive_off = 4, [Description("客戶端主動(dòng)斷開(kāi)")] client_active_off = 5 } }
④關(guān)于客戶端Socket類庫(kù):
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">服務(wù)端ip+port</param> /// <param name="callback">回調(diào)函數(shù)</param> /// <param name="state_object_bufferlen">buffer默認(rèn)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();//開(kāi)始接收數(shù)據(jù) } catch (Exception e) { this._callback(Socket_CallBack_Type.connect_fail, e); } } //開(kāi)始接收數(shù)據(jù) 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); } //接收數(shù)據(jù)返回 private void Async_Receive_Callback(IAsyncResult ar) { State_Object state = (State_Object)ar.AsyncState; try { int byte_read_count = this._client.EndReceive(ar);//接收的字節(jié)數(shù) if (byte_read_count > 0) { state.Buffer_Off_Index += byte_read_count;//增加的數(shù)據(jù)量 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)//包頭的信心已經(jīng)收到 { 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);//取出當(dāng)前的包(一整個(gè)包) state.Buffer_Off_Index = buffer_off_index;//重新賦值 this._callback(Socket_CallBack_Type.receive ,cur_packet);//回調(diào)接收到的包------------------ 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> /// 發(fā)送Socket請(qǐng)求 /// </summary> /// <param name="msg">請(qǐng)求信息</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);//發(fā)送了多少字節(jié) this._callback(Socket_CallBack_Type.send, byte_send_count); } } /// <summary> /// Socket回調(diào)類型 /// </summary> public enum Socket_CallBack_Type : uint { [Description("連接成功")] connect_succ = 0, [Description("連接失敗")] connect_fail = 1, [Description("接收返回")] receive = 2, [Description("發(fā)送返回")] send = 3, [Description("服務(wù)端被迫斷開(kāi)")] server_passive_off = 4, [Description("服務(wù)端主動(dòng)斷開(kāi)")] server_active_off = 5 } }
⑤:服務(wù)端 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數(shù)據(jù) /// </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> /// 構(gòu)造函數(shù) /// </summary> /// <param name="buffer_size">緩存初始的字節(jié)數(shù)</param> public State_Object(int buffer_size = 512) { this._buffer = new byte[buffer_size]; this.Buffer_Off_Index = -1; } /// <summary> /// 字節(jié)數(shù)組 /// </summary> public byte[] Buffer { get { return this._buffer; } } /// <summary> /// 緩存已經(jīng)存儲(chǔ)的下標(biāo)( 顯然從0開(kāi)始 , -1表示沒(méi)有數(shù)據(jù) ) /// </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數(shù)據(jù) /// </summary> internal sealed class State_Object { private byte[] _buffer = null; private int _buffer_off_index = -1; /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="buffer_size">緩存初始的字節(jié)數(shù)</param> public State_Object(int buffer_size = 512) { this._buffer = new byte[buffer_size]; this.Buffer_Off_Index = -1; } /// <summary> /// 字節(jié)數(shù)組 /// </summary> public byte[] Buffer { get { return this._buffer; } } /// <summary> /// 緩存已經(jīng)存儲(chǔ)的下標(biāo)( 顯然從0開(kāi)始 , -1表示沒(méi)有數(shù)據(jù) ) /// </summary> public int Buffer_Off_Index { set { this._buffer_off_index = value; } get { return this._buffer_off_index; } } } }
二,測(cè)試(使用控制臺(tái))
①:服務(wù)端
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;//因?yàn)闇y(cè)試的環(huán)境原因 , 使用 key :姓名 , 在真實(shí)的開(kāi)發(fā)中應(yīng)該使用用戶的ID號(hào) private Svr_Socket _socket = null;//本人封裝的服務(wù)端Socket static void Main(string[] args) { Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.Green; Thread.CurrentThread.IsBackground = true;//退出后自動(dòng)殺死進(jìn)程 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("等待請(qǐng)求連接......."); 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("發(fā)送的字節(jié)數(shù) : {0}", Convert.ToInt32(msg)); break; case Socket_CallBack_Type.client_active_off://主動(dòng)下線 #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); //開(kāi)始啟動(dòng)服務(wù)端的心跳包 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);//發(fā)送聊天信息 } } 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;//退出后自動(dòng)殺死進(jìn)程 Console.Write("請(qǐng)輸入用戶名:"); 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("請(qǐng)求連接Socket服務(wù)器"); 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));//發(fā)送聊天信息 } code = Console.ReadLine(); } } } /// <summary> /// 發(fā)送聊天信息 /// </summary> /// <param name="msg"></param> private void Chat(string chats) { string msg = string.Format("{0} 說(shuō) : {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("發(fā)送的字節(jié)數(shù) : {0}", Convert.ToInt32(msg)); break; case Socket_CallBack_Type.server_active_off: #if DEBUG Console.WriteLine("主動(dòng) : 服務(wù)器斷開(kāi)連接 : {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("被迫 : 服務(wù)器斷開(kāi)連接 : {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("已經(jīng)成功連接到了Socket服務(wù)器了"); } 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},請(qǐng)多指教" , this._name)); Console.WriteLine("{0},請(qǐng)多指教", 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也可以進(jìn)行加密,用于游戲Socket通訊。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。