public static void Stop() { NATServer?.Stop(); HttpServerList.ForEach(c => c.Stop()); TcpServerList.ForEach(c => c.Stop()); MapList.Clear(); }
public static void ChangeMap(int type, Map map) { try { map.ChangeType = type; ChangeMapList(map); var natClient = NATServer.GetSingleSession(c => c.Client?.id == map.client_id); if (natClient == null) { return; } ChangeMap(map, natClient); var pack = PackHelper.CreatePack(new JsonData() { Type = (int)JsonType.NAT, Action = (int)NatAction.MapChange, Data = map.ToJson() }); natClient.Send(pack); } catch (Exception ex) { LogHelper.Error($"映射更新异常:{ex},参数为:{map.ToJson()}"); } }
/*public override void OnHolePunchedClient(int natListenPort, int natConnectPort, bool success) { * base.OnHolePunchedClient(natListenPort, natConnectPort, success); * networkPort = natConnectPort; * * // Make sure to connect to the correct IP or things won't work * if (hostExternalIP == externalIP) { * if (hostInternalIP == Network.player.ipAddress) { * // Host is running on the same computer as client, two separate builds * networkAddress = "127.0.0.1"; * } else { * // Host is on the same local network as client * networkAddress = hostInternalIP; * } * } else { * // Host is somewhere out on the internet * networkAddress = hostExternalIP; * } * * Debug.Log("Attempting to connect to server " + networkAddress + ":" + networkPort); * * // Standard client setup stuff than the NetworkMager would normally take care of for us * NetworkTransport.Init(globalConfig); * if (customConfig) { * foreach (QosType type in base.channels) { * connectionConfig.AddChannel(type); * } * } else { * connectionConfig.AddChannel(QosType.ReliableSequenced); * connectionConfig.AddChannel(QosType.Unreliable); * } * * // If we try to use maxConnection when the Advanced Configuration checkbox is not checked * // we will get a crc mismatch because the host will have been started with the default * // max players of 8 rather than the value in maxConnections * int maxPlayers = 8; * if (customConfig) { * maxPlayers = maxConnections; * } * * HostTopology topo = new HostTopology(connectionConfig, maxPlayers); * * // Start up a transport level host on the port that the hole was punched from * int natListenSocketID = NetworkTransport.AddHost(topo, natListenPort); * * // Create and configure a new NetworkClient * client = new NetworkClient(); * client.Configure(topo); * * // Connect to the port on the server that we punched through to * client.Connect(networkAddress, networkPort); * * // Magic! Set the client's transport level host ID so that the client will use * // the host we just started above instead of the one it creates internally when we call Connect. * // This has to be done so that the connection will be made from the correct port, otherwise * // Unity will use a random port to connect from and NAT Punchthrough will fail. * // This is the shit that keeps me up at night. * clientIDField.SetValue(client, natListenSocketID); * * // Tell Unity to use the client we just created as _the_ client so that OnClientConnect will be called * // and all the other HLAPI stuff just works. Oh god, so nice. * UseExternalClient(client); * StartClient(); * } * public override void OnHolePunchedServer(int natListenPort, ulong clientGUID) { * base.OnHolePunchedServer(natListenPort, clientGUID); * //StartHost(); * }*/ /** * Server received a hole punch from a client * Start up a new NATServer listening on the newly punched hole */ void OnHolePunchedServer(int natListenPort) { NATServer newServer = new NATServer(); bool isListening = newServer.Listen(natListenPort, NetworkServer.hostTopology); if (isListening) { natServers.Add(newServer); } }
static void Main(string[] args) { ConsoleHelper.WriteLine("输入s启动服务器", ConsoleColor.DarkGreen); var input = ConsoleHelper.ReadLine(); if (string.IsNullOrEmpty(input) || input.ToLower() != "s") { ConsoleHelper.WriteLine("输入服务器地址,例如:180.122.325.21:39654", ConsoleColor.DarkGreen); var ipPort = ConsoleHelper.ReadLine(); Peer peer = new Peer(); peer.OnPublicNatInfoResponse += Peer_OnPublicNatInfoResponse;; peer.OnP2pSucess += Peer_OnP2PSucess; peer.OnP2pFailed += Peer_OnP2pFailed; peer.OnMessage += Peer_OnMessage; peer.OnServerDisconnected += Peer_OnServerDisconnected; peer.OnP2pDisconnected += Peer_OnP2pDisconnected; peer.ConnectPeerServer(ipPort); ConsoleHelper.WriteLine("回车查看当前的NatInfo", ConsoleColor.DarkGreen); ConsoleHelper.ReadLine(); peer.RequestPublicNatInfo(); ConsoleHelper.WriteLine("输入PeerB地址发起p2p请求,例如:180.122.325.21:21541", ConsoleColor.DarkGreen); var pIPPort = ConsoleHelper.ReadLine(); ConsoleHelper.WriteLine($"正在向{pIPPort}发起P2p请求。。。", ConsoleColor.DarkGreen); peer.RequestP2p(pIPPort); ConsoleHelper.WriteLine($"与{peer.RemoteNatInfo.ToString()} P2p建立{(peer.IsConnected ? "成功" : "失败")}", ConsoleColor.DarkGreen); TaskHelper.Start(() => { while (peer.IsConnected) { peer.SendMessage("hello p2p"); ThreadHelper.Sleep(1000); } }); } else { NATServer p2pServer = new NATServer(); p2pServer.Start(); ConsoleHelper.WriteLine("回车关闭测试", ConsoleColor.DarkGreen); } ConsoleHelper.ReadLine(); }
private static void TcpServer_NewSessionConnected(TcpAppSession session) { try { //转发请求 var natSession = NATServer.GetSessions(c => c.MapList?.Any(m => m.remote_port == session.LocalEndPoint.Port) ?? false).FirstOrDefault(); if (natSession == null) { session?.Close(); HandleLog.WriteLine($"请求:{session.LocalEndPoint}失败,Nat客户端连接不在线!"); return; } var map = natSession.MapList?.Find(c => c.remote_port == session.LocalEndPoint.Port); if (map == null) { session?.Close(); HandleLog.WriteLine($"请求:{session.LocalEndPoint}失败,映射{session.LocalEndPoint}不存在!"); return; } session.Map = map; var pack = new PackJson() { Host = map?.remote_endpoint, Local = map?.local_endpoint, UserId = session.UserId, Method = "TCP" }; session.PackJson = pack; var json = JsonHelper.Instance.Serialize(pack); var jsonBytes = Encoding.UTF8.GetBytes(json); //03 01 数据长度(4) 正文数据(n) ---tcp连接注册包 var sendBytes = new List <byte>() { 0x3, 0x1 }; sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse()); sendBytes.AddRange(jsonBytes); natSession.Send(sendBytes.ToArray(), 0, sendBytes.Count); session.NatSession = natSession; HandleLog.WriteLine($"客户端【{session.PackJson.UserId},{session.RemoteEndPoint}】已连接【{session.LocalEndPoint}】"); } catch (Exception ex) { HandleLog.WriteLine($"连接【{session.PackJson.UserId},{session.LocalEndPoint}】发生异常:{ex}"); } }
private static void WebServer_NewRequestReceived(WebAppSession session, HttpRequestInfo requestInfo) { Task.Run(() => { try { if (session.RequestTime == null) { session.RequestTime = DateTime.Now; } //转发请求 var host = requestInfo.HeaderDict["Host"]; var natSession = NATServer.GetSessions(c => c.MapList?.Any(m => m.remote_endpoint == host) ?? false).FirstOrDefault(); if (natSession == null) { session?.Close(); HandleLog.WriteLine($"请求:{host}失败,Nat客户端连接不在线!"); return; } var pack = new PackJson() { Host = host, UserId = session.UserId, Method = requestInfo.Method, Route = requestInfo.Route, Headers = requestInfo.HeaderDict, Content = requestInfo.Content }; var json = JsonHelper.Instance.Serialize(pack); var jsonBytes = Encoding.UTF8.GetBytes(json); //02 01 数据长度(4) 正文数据(n) ---http响应包 var sendBytes = new List <byte>() { 0x2, 0x1 }; sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse()); sendBytes.AddRange(jsonBytes); natSession.Send(sendBytes.ToArray(), 0, sendBytes.Count); } catch (Exception ex) { HandleLog.WriteLine($"【{session.RemoteEndPoint}】请求参数:{Encoding.UTF8.GetString(requestInfo.Data)},处理发生异常:{ex}"); } }); }
public static void ChangeMap(int type, Map map) { try { map.ChangeType = type; ChangeMap(map); var pack = PackHelper.CreatePack(new JsonData() { Type = (int)JsonType.NAT, Action = (int)NatAction.MapChange, Data = map.ToJson() }); var natClient = NATServer.GetSingle(c => c.Client?.id == map.client_id); natClient?.Send(pack); } catch (Exception ex) { HandleLog.WriteLine($"映射更新异常:{ex},参数为:{JsonHelper.Instance.Serialize(map)}"); } }
private static void NATServer() { NATServer host = new NATServer(new NetConfiguration(5001) { Port = 5000, AllowConnectors = true, MaxConnections = 5, Name = "NATServer", Timeout = 1, NetworkRate = 50 }, 1024); host.Start(); while (isPooling) { host.Tick(); Thread.Sleep(50); } }
public static void ChangeMap(int type, Map map) { try { map.ChangeType = type; ChangeMap(map); //请求头 01 04 长度(4) var sendBytes = new List <byte>() { 0x1, 0x4 }; var jsonBytes = Encoding.UTF8.GetBytes(JsonHelper.Instance.Serialize(map)); sendBytes.AddRange(BitConverter.GetBytes(jsonBytes.Length).Reverse()); sendBytes.AddRange(jsonBytes); var natClient = NATServer.GetSessions(c => c.Client?.id == map.client_id).FirstOrDefault(); natClient?.Send(sendBytes.ToArray()); } catch (Exception ex) { HandleLog.WriteLine($"映射更新异常:{ex},参数为:{JsonHelper.Instance.Serialize(map)}"); } }
private static void Received(NatSession session, NatRequestInfo requestInfo) { Task.Run(() => { try { switch (requestInfo.Body.Type) { case (byte)JsonType.NAT: { LogHelper.Info($"NAT收到数据:{requestInfo.Raw.ToHexWithSpace()},正文内容: {requestInfo.Body.ToJson()}", false); NATServer.ProcessData(session, requestInfo); break; } case (byte)JsonType.HTTP: { var httpModel = requestInfo.Body.Data.FromJson <HttpModel>(); var server = HttpServerList.Find(c => c.ServerId == httpModel.ServerId); server?.ProcessData(session, requestInfo, httpModel); break; } case (byte)JsonType.TCP: { var tcpModel = requestInfo.Body.Data.FromJson <TcpModel>(); var server = TcpServerList.Find(c => c.ServerId == tcpModel.ServerId); server?.ProcessData(session, requestInfo, tcpModel); break; } } } catch (Exception ex) { LogHelper.Error($"穿透传输连接【{session.RemoteEndPoint},{session.Client?.name}】响应请求异常:{ex}"); } }); }
static void ChangeMap(Map map) { try { var session = NATServer.GetSessions(c => c.Client.id == map.client_id).FirstOrDefault(); if (session == null) { return; } if (session.MapList == null) { session.MapList = new List <Map>(); } switch (map.ChangeType) { case (int)ChangeMapType.新增: session.MapList.Add(map); break; case (int)ChangeMapType.修改: session.MapList.RemoveAll(c => c.id == map.id); session.MapList.Add(map); break; case (int)ChangeMapType.除: session.MapList.RemoveAll(c => c.id == map.id); break; } HandleLog.WriteLine($"映射{Enum.GetName(typeof(ChangeMapType), map.ChangeType)}成功:{JsonHelper.Instance.Serialize(map)}", false); HandleLog.WriteLine($"【{map.name}】映射{Enum.GetName(typeof(ChangeMapType), map.ChangeType)}成功:{map.local_endpoint} --> {map.remote_endpoint}"); } catch (Exception ex) { throw ex; } }
private static void NATServer_NewRequestReceived(NatAppSession session, NatRequestInfo requestInfo) { Task.Run(() => { try { //HandleLog.WriteLine($"NAT服务收到数据:{requestInfo.Hex}"); if (requestInfo.Mode == 0x1)//nat { switch (requestInfo.FunCode) { case 0x1: { //注册包 var secret = requestInfo.BodyRaw; using var bll = new ClientBll(); var client = bll.GetOne(secret).Data; if (client == null) { HandleLog.WriteLine($"主机【{session.RemoteEndPoint}】密钥不正确!!"); session.SendMsg("主机密钥不正确,请确认是否填写正确!"); return; } var checkSessions = NATServer.GetSessions(c => c.Client?.secret == secret).ToList(); if (checkSessions.Any()) { checkSessions.ForEach(c => { session.SendMsg($"您的密钥已被主机{client.name},{session.RemoteEndPoint}使用,已强制下线!!"); Thread.Sleep(500); c.Close(); }); } session.Client = client; using var mapBll = new MapBll(); session.MapList = mapBll.GetMapList(secret).Data ?? new List <Map>(); //原样返回回复客户端注册成功 session.Send(requestInfo.Data); Task.Run(() => { //更新在线状态 using var bll = new ClientBll(); var updateRst = bll.UpdateOnlineStatus(new Client() { secret = session.Client.secret, is_online = true, last_heart_time = DateTime.Now }); HandleLog.WriteLine($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false); }); } break; case 0x2: { //心跳包 var secret = requestInfo.BodyRaw; HandleLog.WriteLine($"收到连接{session.RemoteEndPoint}的心跳包,密钥为:{secret},当前映射个数:{session.MapList.Count}", false); Task.Run(() => { //更新在线状态 using var bll = new ClientBll(); var updateRst = bll.UpdateOnlineStatus(new Client() { secret = session.Client.secret, is_online = true, last_heart_time = DateTime.Now }); HandleLog.WriteLine($"更新主机【{session.Client.name}】在线状态结果:{updateRst.Message}", false); }); } break; } } else if (requestInfo.Mode == 0x2)//http { var packJson = JsonHelper.Instance.Deserialize <PackJson>(requestInfo.BodyRaw); switch (requestInfo.FunCode) { case 0x1: { //02 01 数据长度(4) 正文数据(n) ---http响应包 int count = 0; mark: var webSession = HttpServerList.SelectMany(c => c.GetAllSessions()).Where(c => c.UserId.ToLower() == packJson.UserId.ToLower()).FirstOrDefault(); if (webSession == null) { count++; Thread.Sleep(500); if (count < 5) { goto mark; } HandleLog.WriteLine($"webSession【{packJson.UserId}】不存在"); return; } //先讲16进制字符串转为byte数组 再gzip解压 var response = DataHelper.Decompress(packJson.Content); var res = webSession.TrySend(response, 0, response.Length); HandleLog.WriteLine($"{packJson.ResponseInfo} {Math.Ceiling((DateTime.Now - webSession.RequestTime).Value.TotalMilliseconds)}ms"); } break; } } else if (requestInfo.Mode == 0x3)//tcp { var packJson = JsonHelper.Instance.Deserialize <PackJson>(requestInfo.BodyRaw); switch (requestInfo.FunCode) { case 0x2: { //响应请求 int count = 0; mark: var tcpSession = TcpServerList.SelectMany(c => c.GetAllSessions()).Where(c => c.UserId.ToLower() == packJson.UserId.ToLower()).FirstOrDefault(); if (tcpSession == null) { count++; Thread.Sleep(500); if (count < 5) { goto mark; } HandleLog.WriteLine($"tcpSession【{packJson.UserId}】不存在"); return; } //先讲16进制字符串转为byte数组 再gzip解压 var response = DataHelper.Decompress(packJson.Content); tcpSession.Send(response, 0, response.Length); HandleLog.WriteLine($"----> {tcpSession.PackJson.UserId} 发送报文{response.Length}字节"); } break; case 0x3: { //响应请求 var tcpSession = TcpServerList.SelectMany(c => c.GetAllSessions()).Where(c => c.UserId.ToLower() == packJson.UserId.ToLower()).FirstOrDefault(); if (tcpSession != null) { tcpSession.Close(); HandleLog.WriteLine($"连接【{tcpSession.PackJson.UserId},{tcpSession.RemoteEndPoint}】关闭成功"); } } break; } } } catch (Exception ex) { HandleLog.WriteLine($"穿透传输连接【{session.RemoteEndPoint},{session.Client?.name}】响应请求异常:{ex}"); } }); }
public void Stop() { NATServer?.Stop(); HttpServerList?.ForEach(c => c.Stop()); TcpServerList?.ForEach(c => c.Stop()); }
private void OnHandleContext(IAsyncResult ar) { try { //继续异步监听下一次请求 HttpListener.BeginGetContext(OnHandleContext, HttpListener); //当前请求上下文 var context = HttpListener.EndGetContext(ar); //转发请求 var natSession = NATServer.GetSingle(c => c.MapList.Any(c => c.remote_endpoint == context.Request.Url.Authority)); if (natSession == null) { //TODO 错误页面 HandleLog.WriteLine($"穿透客户端未连接到服务器,请求地址:{context.Request.Url.AbsoluteUri}"); context.Response.StatusCode = 404; var returnByteArr = Encoding.UTF8.GetBytes("nat client not found"); using var stream = context.Response.OutputStream; //把处理信息返回到客户端 stream.WriteAsync(returnByteArr, 0, returnByteArr.Length); } else { var sessionId = Guid.NewGuid().ToString(); ContextDict.Add(sessionId, context); var map = natSession.MapList.Find(c => c.remote_endpoint == context.Request.Url.Authority); var httpModel = new HttpModel() { RequestTime = DateTime.Now, ServerId = ServerId, HttpVersion = $"{map?.protocol.ToUpper()}/{context.Request.ProtocolVersion.ToString()}", Host = context.Request.Url.Authority, SessionId = sessionId, Method = context.Request.HttpMethod, Path = context.Request.RawUrl, Headers = context.Request.Headers.ToDictionary(), ContentType = context.Request.ContentType }; var byteList = new List <byte>(); int readLen = 0; int len = 0; if (context.Request.HttpMethod != "Get") { var byteArr = new byte[2048]; do { readLen = context.Request.InputStream.Read(byteArr, 0, byteArr.Length); len += readLen; byteList.AddRange(byteArr); } while (readLen != 0); var byteData = byteList.CloneRange(0, len); var req = byteData.ToUTF8String(); if (byteData.Length > 0) { //压缩请求数据 var body = DataHelper.Compress(byteData); httpModel.Content = body; } } natSession?.Send(PackHelper.CreatePack(new JsonData() { Type = (int)JsonType.HTTP, Action = (int)HttpAction.Request, Data = httpModel.ToJson() })); } } catch (Exception ex) { HandleLog.WriteLine($"HttpServer OnHandleContext穿透处理异常,{ex}"); } }