中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C# 異步Socket

發布時間:2020-07-03 06:30:25 來源:網絡 閱讀:1916 作者:Aonaufly 欄目:編程語言

先看看測試結果:

服務端:

C# 異步Socket

服務器端控制臺:

C# 異步Socket

可以發現我服務端連了2個客戶端,第一個為局域網的一臺機器,另一個為服務器的主機


ip為192.168.1.105 ,端口為42794的客戶端:

C# 異步Socket

ip為192.168.1.104,端口為30547的客戶端:

C# 異步Socket


需要發送聊天信息 : 使用“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通訊。

附件:http://down.51cto.com/data/2366908
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

蓬莱市| 澄迈县| 拉萨市| 富顺县| 荣昌县| 陕西省| 万全县| 新密市| 南丰县| 洪湖市| 诸城市| 梁山县| 常山县| 穆棱市| 台中县| 全州县| 武城县| 阜新| 札达县| 长宁县| 玉溪市| 阿拉善右旗| 吉木乃县| 沈丘县| 呈贡县| 皮山县| 民乐县| 铁岭市| 平定县| 建阳市| 盐城市| 蒙阴县| 闸北区| 乌鲁木齐县| 台中县| 攀枝花市| 景泰县| 绥阳县| 万安县| 阳曲县| 巴林左旗|