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

2

Я написал сервер сокетов в С#, который будет использоваться в качестве основного дизайна для небольшого игрового проекта, частью которого я являюсь. Сервер сокетов отлично работает на LAN. Я могу полностью общаться между сервером и клиентом. Однако на WAN сервер получает все правильные сообщения от клиента, но клиент не получает сообщений с сервера. И клиент, и сервер находятся за маршрутизатором, но только серверный маршрутизатор имеет перенаправленные порты. Когда клиент подключается к серверу, я получаю 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); 

    }
  • 0
    это может звучать очень глупо (но мы все иногда делаем глупые ошибки), но вы не просто отправляете UDP-пакеты с сервера на IP-адрес / порт клиента, верно?
  • 0
    Сначала я получаю IP-адрес из TCP-соединения при первоначальном входе в систему, затем использую UDP для отправки сообщений туда и обратно. Я проверю, но я верю, что они отправляются правильно. Вы правы, дважды проверяя, что такие вещи, безусловно, необходимы
Показать ещё 7 комментариев
Теги:
tcp
network-programming
udp
wan

1 ответ

2
Лучший ответ

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

  • 0
    Я вижу, где я совершил ошибку, спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню