c# - WAN 上的 TCP/UDP 套接字服务器

标签 c# tcp network-programming udp wan

我用 C# 编写了一个套接字服务器,它将用作我参与的一个小型游戏项目的基本设计。套接字服务器在局域网上工作正常。我能够在服务器和客户端之间完全正常地通信。但是在 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); 

    }

最佳答案

客户端必须启动 UDP 通信,这样它才能在路由器/防火墙中找到一个“洞”。 UDP 服务器必须使用 ReceviedFrom

中引用的端点进行回复

关于c# - WAN 上的 TCP/UDP 套接字服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7018796/

相关文章:

C# - 如何在连接到 (RAS) VPN 时获取 IP 地址

c# - 使用 WebClient 将数据发布到 SSRS 报告服务器

c# - 为什么我的 WindsorContainer 不能解析 IWindsorContainer?

c# - 通过 TCP 套接字丢失一个字节

c - 禁用退避延迟

c++ - 持续的 ASIO 连接

c# - 连接的TCP套接字如何同时发送/接收多个文件?

linux - 我应该使用 netcat 在端口 25 上查看电子邮件吗?

c# - Elasticsearch Nest 6.5.1。我如何将原始请求发送到Elasticsearch

c# - 如何显示异常消息 (Razor/C#)