123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- using System;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Threading.Channels;
- using System.Linq;
- using System.Net.Http;
- using System.Collections.Generic;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Diagnostics;
- using ProtoDataBuff;
- using MultiDup;
- using pb = global::Google.Protobuf;
- namespace clientTest.multiDup
- {
- class Program
- {
- static readonly Random r = new Random();
- /// <summary>
- /// 消息分发
- /// </summary>
- static private Dictionary<eProtocalCommand, Action<sSocketData>> callbacks = new Dictionary<eProtocalCommand, Action<sSocketData>>();
- static void Main(string[] args)
- {
- callbacks.Add(eProtocalCommand.ScMdGetRoomList, On_update);
- callbacks.Add(eProtocalCommand.ScMdEnterRoom, On_enter);
- callbacks.Add(eProtocalCommand.ScMdBeginDup, On_begin);
- callbacks.Add(eProtocalCommand.ScMdLeaveRoom, On_GameOver);
- callbacks.Add(eProtocalCommand.ScMdCreateRoom, On_CreateRoom);
- var n = 1;
- var list = new Task[n];
- for (int i = 0; i < n; i++)
- {
- list[i] = Task.Run(async () => await send());
- }
- Task.Run(Dispatch);
- Task.WaitAll(list);
- }
- #region 收到消息处理
- /// <summary>
- /// 更新房间列表
- /// </summary>
- static void On_update(sSocketData data)
- {
- Console.WriteLine("最新房间列表: {}");
- }
- /// <summary>
- /// 客户端进入房间
- /// </summary>
- static void On_CreateRoom(sSocketData data)
- {
- Console.WriteLine("xxx创建了房间.");
- }
- /// <summary>
- /// 客户端进入房间
- /// </summary>
- static void On_begin(sSocketData data)
- {
- var msg = SC_MD_BeginDup.Parser.ParseFrom(data._data);
- Console.WriteLine("xxx开始了游戏.");
- Console.WriteLine($"正在连接{msg.Battleserver}:{msg.BattleServerPort}");
- var endPoint = new IPEndPoint(IPAddress.Parse(msg.Battleserver), msg.BattleServerPort);
- //var endPoint = new IPEndPoint(IPAddress.Loopback, port);
- //var endPoint = new IPEndPoint(IPAddress.Parse("115.159.121.129"), port);
- using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
- {
- try
- {
- client.ConnectAsync(endPoint).Wait();
- }
- catch (Exception ee)
- {
- Debug.WriteLine(ee.Message);
- }
- if (client.Connected)
- {
- Thread.Sleep(2000);
- var t = Task.Run(() => recv(client)); // 开启recv监听协程
- try
- {
- BtLogIn(client).Wait();
- // 连上来之后, 创建房间, 开始游戏, 退出房间
- BtBroadCast(client).Wait();
- BtBroadCast(client).Wait();
- BtBroadCast(client).Wait();
- Console.WriteLine("已经广播3次,exiting.");
- }
- catch (Exception e)
- {
- client.Close();
- }
- finally
- {
- client.Close();
- }
- }
- else {
- Console.WriteLine("连接失败!");
- }
- }
- }
- /// <summary>
- /// 客户端进入房间
- /// </summary>
- static void On_enter(sSocketData data)
- {
- Console.WriteLine("xx进入了房间.");
- }
- /// <summary>
- /// 处理客户端上报伤害请求
- /// </summary>
- static void On_GameOver(sSocketData data)
- {
- Console.WriteLine("xx已离开房间! ");
- //Task.Delay(3000).ContinueWith(t => Environment.Exit(0));
- }
- #endregion
- async static Task BtLogIn(Socket sock)
- {
- try
- {
- var msg = new CS_BT_Login() { Msg = $"来自客户端{Environment.UserDomainName}的登录,{DateTime.Now.ToString()}", Uid = Environment.MachineName, Zoneid = 1 };
- var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsBtLogin, IMsg2Bytes(msg)));
- await sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- catch (Exception e)
- {
- sock.Close();
- }
- }
- async static Task BtBroadCast(Socket sock)
- {
- try
- {
- var msg = new CS_BT_BroadCast() { Msg = $"来自客户端{Environment.UserDomainName}的广播,{DateTime.Now.ToString()}", SenderUid = Environment.MachineName, Zoneid = 1 };
- var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsBtBroadCast, IMsg2Bytes(msg)));
- await sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- catch (Exception e)
- {
- sock.Close();
- }
- }
- static async Task send()
- {
- var port = 6004;
- var endPoint = new IPEndPoint(IPAddress.Parse("192.168.10.17"), port);
- //var endPoint = new IPEndPoint(IPAddress.Loopback, port);
- //var endPoint = new IPEndPoint(IPAddress.Parse("115.159.121.129"), port);
- using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
- {
- try
- {
- await client.ConnectAsync(endPoint);
- }
- catch (Exception ee)
- {
- Debug.WriteLine(ee.Message);
- }
- var t = Task.Run(() => recv(client)); // 开启recv监听协程
- try
- {
- // 连上来之后, 创建房间, 开始游戏, 退出房间
- CreateRoom(client).Wait();
- Thread.Sleep(r.Next(1000, 3000));
- await BeginGame(client);
- Thread.Sleep(r.Next(1000, 3000));
- Console.ReadKey();
- await LeaveGame(client);
- Thread.Sleep(r.Next(1000, 3000));
- }
- catch (Exception e)
- {
- client.Close();
- }
- finally
- {
- client.Close();
- }
- }
- }
- /// <summary>
- /// 创建房间
- /// </summary>
- /// <param name="Sock"></param>
- /// <returns></returns>
- async static Task CreateRoom(Socket Sock)
- {
- try
- {
- var msg = new CS_MD_CreateRoom() { Uid = Environment.MachineName, Zoneid = 1 };
- var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsMdCreateRoom, IMsg2Bytes(msg)));
- await Sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- catch (Exception e)
- {
- Sock.Close();
- }
- }
- /// <summary>
- /// 开始游戏
- /// </summary>
- /// <param name="sock"></param>
- /// <returns></returns>
- async static Task BeginGame(Socket sock)
- {
- var msg = new CS_MD_BeginDup() { Uid = Environment.MachineName, Zoneid = 1 };
- var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsMdBeginDup, IMsg2Bytes(msg)));
- await sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- /// <summary>
- /// 离开游戏
- /// </summary>
- /// <param name="sock"></param>
- /// <returns></returns>
- async static Task LeaveGame(Socket sock)
- {
- var msg = new CS_MD_LeaveRoom() { Uid = Environment.MachineName, Zoneid = 1 };
- var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsMdLeaveRoom, IMsg2Bytes(msg)));
- await sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- #region 消息收发
- static byte[] IMsg2Bytes(pb::IMessage msg)
- {
- using var ms = new MemoryStream();
- using var goutstream = new pb::CodedOutputStream(ms);
- msg.WriteTo(goutstream);
- goutstream.Flush();
- ms.Seek(0, SeekOrigin.Begin);
- return ms.ToArray();
- }
- static async void Dispatch()
- {
- while (true)
- {
- var msg = await recvDataBuffer.Reader.ReadAsync();
- if (callbacks.ContainsKey(msg._protocallType))
- {
- callbacks[msg._protocallType](msg);
- }
- else
- {
- // 未找到消息处理逻辑
- Console.WriteLine("未识别的消息类型:" + msg._protocallType.ToString());
- }
- }
- Console.WriteLine("dispatch 已退出");
- }
- /// <summary>
- /// 向客户端写入消息
- /// </summary>
- static async void WriteToserver(Socket Sock)
- {
- while (true)
- {
- var msg = await sendDataBuffer.Reader.ReadAsync();
- var data = SocketDataToBytes(msg);
- await Sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
- }
- }
- /// <summary>
- /// 网络结构转数据
- /// </summary>
- /// <param name="tmpSocketData"></param>
- /// <returns></returns>
- static private byte[] SocketDataToBytes(sSocketData tmpSocketData)
- {
- byte[] _tmpBuff = new byte[tmpSocketData.PackLen];
- byte[] _tmpBuffLength = BitConverter.GetBytes(tmpSocketData.PackLen);
- byte[] _tmpDataLenght = BitConverter.GetBytes((UInt16)tmpSocketData._protocallType);
- Array.Copy(_tmpBuffLength, 0, _tmpBuff, 0, Constants.HEAD_DATA_LEN);//缓存总长度
- Array.Copy(_tmpDataLenght, 0, _tmpBuff, Constants.HEAD_DATA_LEN, Constants.HEAD_TYPE_LEN);//协议类型
- Array.Copy(tmpSocketData._data, 0, _tmpBuff, Constants.HEAD_LEN, tmpSocketData.DataLen());//协议数据
- return _tmpBuff;
- }
- /// <summary>
- /// 数据转网络结构
- /// </summary>
- /// <param name="_protocalType"></param>
- /// <param name="_data"></param>
- /// <returns></returns>
- static private sSocketData BytesToSocketData(eProtocalCommand _protocalType, byte[] _data)
- {
- sSocketData tmpSocketData = new sSocketData();
- tmpSocketData.PackLen = Constants.HEAD_LEN + _data.Length;
- //tmpSocketData._dataLength = _data.Length;
- tmpSocketData._protocallType = _protocalType;
- tmpSocketData._data = _data;
- return tmpSocketData;
- }
- /// <summary>
- /// 接收buffer
- /// </summary>
- static private Channel<sSocketData> recvDataBuffer = Channel.CreateUnbounded<sSocketData>();
- /// <summary>
- /// 发送buffer
- /// </summary>
- static private Channel<sSocketData> sendDataBuffer = Channel.CreateUnbounded<sSocketData>();
- /// <summary>
- /// 接收客户端发来的信息,客户端套接字对象
- /// </summary>
- /// <param name="socketclientpara"></param>
- static async void recv(Socket socketServer)
- {
- socketServer.ReceiveTimeout = 800; // 接收等待超时时间设为800毫秒
- var _databuffer = new DataBuffer();
- byte[] arrServerRecMsg = new byte[4096]; // 创建一个内存缓冲区,其大小为4k字节
- while (true)
- {
- try
- {
- var length = await socketServer.ReceiveAsync(new ArraySegment<byte>(arrServerRecMsg), SocketFlags.None); // 将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
- if (length <= 0) // 视为客户端已经close连接
- {
- break;
- }
- _databuffer.AddBuffer(arrServerRecMsg, length); //将收到的数据添加到缓存器中
- while (_databuffer.GetData(out sSocketData _socketData)) //取出一条完整数据
- {
- Console.WriteLine(socketServer.GetHashCode().ToString() + " recv: " + _socketData._protocallType);
- await recvDataBuffer.Writer.WriteAsync(_socketData); // 放入channel
- }
- Array.Clear(arrServerRecMsg, 0, length);
- }
- catch (SocketException e)
- {
- if (e.ErrorCode == 10060) // 超时的时候错误号码是10060
- {
- continue; // 继续等待
- }
- break;
- }
- catch (Exception)
- {
- break;
- }
- }
- Console.WriteLine(socketServer.GetHashCode().ToString() + "recv 已退出");
- socketServer.Close(); // 关闭之前accept出来的和客户端进行通信的套接字
- }
- #endregion
- }
- }
|