先看看测试结果:
服务端:
服务器端控制台:
可以发现我服务端连了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通讯。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。