Сокет-сервер TCP / UDP в глобальной сети - PullRequest
2 голосов
/ 11 августа 2011

Я написал сервер сокетов в c #, который будет использоваться в качестве базового проекта для небольшого игрового проекта, частью которого я являюсь. Сервер сокетов отлично работает на локальной сети. Я могу нормально общаться между сервером и клиентом. Однако в глобальной сети сервер получает все правильные сообщения от клиента, но клиент не получает сообщений от сервера. И клиент, и сервер находятся за маршрутизатором, но только маршрутизатор сервера имеет перенаправленные порты. Когда клиент подключается к серверу, я получаю IP-адрес подключения. Поскольку клиент находится за NAT, нужно ли мне собирать дополнительную информацию от отправителя? Я предполагаю, что клиент может настроить переадресацию портов, но это ОЧЕНЬ неэффективно для игры. Любая помощь, которую я могу получить, ценится. Если вам нужен код, дайте мне знать. Заранее спасибо.

Используется для установления TCP-соединения с клиента

public string ConnectionAttempt(string ServeIP, string PlayUsername)
    {
        username = PlayUsername;

        try
        {

            connectionClient = new TcpClient(ServeIP,TCP_PORT_NUMBER);
            connectionClient.GetStream().BeginRead(readbuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DoRead), null);

            Login(username);
            ipAddress = IPAddress.Parse(((IPEndPoint)connectionClient.Client.RemoteEndPoint).Address.ToString());
            servIP = new IPEndPoint(ipAddress,65002);
            listenUDP = new IPEndPoint(ipAddress, 0);

            UDPListenerThread = new Thread(receiveUDP);
            UDPListenerThread.IsBackground = true;
            UDPListenerThread.Start();
            return "Connection Succeeded";
        }
        catch(Exception ex) {
            return (ex.Message.ToString() + "Connection Failed");
        }
    }

Прослушивает UDP-сообщение в потоке.

private void receiveUDP()
    {
        System.Net.IPEndPoint test = new   System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
        System.Net.EndPoint serverIP = (System.Net.EndPoint)test;
        server.Bind(serverIP);

        EndPoint RemoteServ = (EndPoint)servIP;
        while (true)
        {
            byte[] content = new byte[1024];
            int  data = server.ReceiveFrom(content, ref RemoteServ);

            string message = Encoding.ASCII.GetString(content);
            result = message;

            ProcessCommands(message);

        }
    }

Прослушиватель TCP-соединения с сервером:

private void ConnectionListen()
    {
        try
        {
            listener = new TcpListener(System.Net.IPAddress.Any, PORT_NUM);
            listener.Start();

            do
            {
                UserConnection client = new UserConnection(listener.AcceptTcpClient());
                client.LineRecieved += new LineRecieve(OnLineRecieved);
                UpdateStatus("Someone is attempting a login");

            } while (true);
        }
        catch
        {
        }
    }

Прослушиватель UDP сервера:

private void receiveUDP()
    {
        System.Net.IPEndPoint test = new System.Net.IPEndPoint(System.Net.IPAddress.Any, UDP_PORT);
        System.Net.EndPoint serverIP = (System.Net.EndPoint)test;
        trans.Bind(serverIP);
        System.Net.IPEndPoint ipep = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
        System.Net.EndPoint Remote = (System.Net.EndPoint)ipep;

        while (true)
        {

            byte[] content = new byte[1024];

            int recv = trans.ReceiveFrom(content,ref Remote);


            string message = Encoding.ASCII.GetString(content);
            string[] data = message.Split((char)124);
            //UpdateStatus(data[0] + data[1]);

            UserConnection sender = (UserConnection)clients[data[0]];
            sender.RemoteAdd = Remote;
            if (data.Length > 2)
            {
                OnLineRecieved(sender, data[1] + "|" + data[2]);
            }
            else
            {
                OnLineRecieved(sender, data[1]);
            }
        }
    }

Информация о настройке для подключения пользователя на стороне сервера:

Socket trans = new Socket(AddressFamily.InterNetwork,
                 SocketType.Dgram, ProtocolType.Udp); //UDP connection for data transmission in game.

    public PlayerLoc Location = new PlayerLoc();

    public UserConnection(TcpClient client)//TCP connection established first in the Constructor
    {
        this.client = client;
        ipAdd = IPAddress.Parse(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
        ipep = new IPEndPoint(ipAdd, ((IPEndPoint)client.Client.RemoteEndPoint).Port);
        this.client.GetStream().BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(StreamReciever), null);
    }

Способ отправки данных отдельным пользователям:

public void SendData(string data)//UDP only used during transmission
    {

        byte[] dataArr = Encoding.ASCII.GetBytes(data);
        trans.SendTo(dataArr, dataArr.Length,SocketFlags.None, RemoteAdd); 

    }

1 Ответ

2 голосов
/ 12 августа 2011

Клиент должен начать связь UDP, чтобы он мог получить «дыру» в маршрутизаторе / брандмауэре. И UDP-сервер должен ответить обратно, используя конечную точку, указанную в ReceviedFrom

...