Beispiel #1
0
 public static void Stop()
 {
     NATServer?.Stop();
     HttpServerList.ForEach(c => c.Stop());
     TcpServerList.ForEach(c => c.Stop());
     MapList.Clear();
 }
Beispiel #2
0
        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()}");
            }
        }
Beispiel #3
0
    /*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);
        }
    }
Beispiel #4
0
        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();
        }
Beispiel #5
0
        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}");
            }
        }
Beispiel #6
0
 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}");
         }
     });
 }
Beispiel #7
0
        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)}");
            }
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
 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)}");
     }
 }
Beispiel #10
0
        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}");
                }
            });
        }
Beispiel #11
0
        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;
            }
        }
Beispiel #12
0
        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}");
                }
            });
        }
Beispiel #13
0
 public void Stop()
 {
     NATServer?.Stop();
     HttpServerList?.ForEach(c => c.Stop());
     TcpServerList?.ForEach(c => c.Stop());
 }
Beispiel #14
0
        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}");
            }
        }