按道理来说symmetic NAT 后的机器只要先给SERVER 发包,SERVER 收到后立刻回包应该和Client1是能够通讯上的. 不知道你的为什么?
是不是你NAT后有多于1个的公网IP? 

解决方案 »

  1.   

    对于symmetic NAT, 打开的端口会变化, 也就是在symmetic NAT 后的机器A给Server发送包后,symmetic NAT打开的端口就会改变,所以此时外网发送到这端口的包就会被丢弃。
    在这种NAT上建立P2P通讯是很困难的。有的说用端口猜测, 但也不容易成功。
      

  2.   

    不会吧,Symmetric NAT虽然不能用于P2P(就是不能打洞吧),但是和公网主机通讯还是可以的,只要是他先发包.我估计是NAT前有多台主机都在用同一个端口发UDP数据
    Symmetric NAT: 内网主机建立一个UDP socket(LocalIP,LocalPort),当用这个socket第一次发数据给外部主机1时,NAT为其映射一个(PublicIP-1,Port-1),以后内网主机发送给外部主机1的所有数据都是用这个(PublicIP-1,Port-1),如果内网主机同时用这个socket给外部主机2发送数据,第一次发送时,NAT会为其分配一个(PublicIP-2,Port-2), 以后内网主机发送给外部主机2的所有数据都是用这个(PublicIP-2,Port-2).如果NAT有多于一个公网IP,则PublicIP-1和PublicIP-2可能不同,如果NAT只有一个公网IP,则Port-1和Port-2肯定不同,也就是说一定不能是PublicIP-1等于 PublicIP-2且Port-1等于Port-2。此外,如果任何外部主机想要发送数据给这个内网主机,那么它首先应该收到内网主机发给他的数据,然后才能往回发送,否则即使他知道内网主机的一个(PublicIP,Port)也不能发送数据给内网主机,这种NAT无法实现UDP-P2P通信。 
      

  3.   

    不知道楼主是如何回复侦听信息的,UDP能回复信息么?我感觉好像不行吧,试试用TCP形势的
    服务器侦听这样:
                    Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket类                Socket c = null;
                    while (true)                   {
                        try
                        {
    c = sock .Accept();
    //这个c 发来信息后,就可以给客户端回复信息了,如果需要一直使用,可用一个实例保存这个SOCKET,这个SOCKET就是你和客户端通讯的东西喽!
    //信息接收完成后,再继续开始一个侦听,然后跳出循环
    }
    catch
    {}
    }
      

  4.   

    我贴下代码,先贴服务器的
    这个运行在服务器上,有外网IP 监听UPD报  private void StartListener()
            {
                int 端口 =56565; //设置端口
                UdpClient listener = new UdpClient(端口); //使用UDP协议            IPEndPoint ip = new IPEndPoint(IPAddress.Any, 端口); //任意IP,
         
                                    while (true)//使用永真循环另其一直处于监听状态
                                    {
                                        byte[] bytes = listener.Receive(ref  ip);                                    string 文本 = Encoding.GetEncoding("gb2312").GetString(bytes, 0, bytes.Length);//获得信息
                                        
                                        回应c1(ip.Address.ToString(), ip.Port);
                                        
                                        MessageBox.Show("[IP:"+ip.Address+"]"+"[端口"+ip.Port+"]以返回");
                                    }
             
            }
    这个是服务器收到后,往客户端发的报(也就是问题所在,客户端收不到服务器的报)
    private void 回应c1(string ip,int dk)
            {            Socket s = new Socket(AddressFamily.InterNetwork,
                SocketType.Dgram, ProtocolType.Udp);
                IPAddress broadcast = IPAddress.Parse(ip);            byte[] sendbuf =            Encoding.GetEncoding("gb2312").GetBytes("服务器与你取得联系了");            IPEndPoint ep = new IPEndPoint(broadcast, Convert.ToInt32(dk));            s.SendTo(sendbuf, ep);//发送信息
            }
      

  5.   

    这个是客户端向服务器发报(服务器可以收到)
     Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp);//实例化Socket对象
              
                //IP
                IPAddress broadcast = IPAddress.Parse(this.textBox1.Text.ToString());
              
                //转换要发送的数据
                byte[] sendbuf =Encoding.GetEncoding("gb2312").GetBytes(this.textBox2.Text.ToString());            //IP 和 端口
                IPEndPoint ep = new IPEndPoint(broadcast,Convert.ToInt32(textBox3.Text));            //发送信息
                s.SendTo(sendbuf, ep);这里是客户端监听 又服务器回发的报(收不到)  UdpClient listenerp = new UdpClient(56565); //使用UDP协议
                IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 56565); //任意IP,
                try
                {
                    while (true)//使用永真循环另其一直处于监听状态
                    {
                        byte[] bytes = listenerp.Receive(ref  groupEP);
                        string 文本 = Encoding.GetEncoding("gb2312").GetString(bytes, 0, bytes.Length);//获得信息
                        MessageBox.Show("SERVER回应:"+文本 + ":" );
                    }
                }
                catch (Exception e)
                {
                    listenerp.Close();
                    MessageBox.Show(e.ToString());
                }
      

  6.   

    嗯,习惯思维,当成两个是在内肉了。
    分析楼主的代码:你是向Serve的56565端口发消息,但你本地绑定的端口不一定就是56565,所以当服务器回发的时候,数据到达NAT时,NAT就会把它转发到本地发送时绑定的端口,而不一定就是56565。
    //这个是客户端向服务器发报(服务器可以收到) 
    Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Dgram, ProtocolType.Udp);//实例化Socket对象
              
                //IP
                IPAddress broadcast = IPAddress.Parse(this.textBox1.Text.ToString());
              
                //转换要发送的数据
                byte[] sendbuf =Encoding.GetEncoding("gb2312").GetBytes(this.textBox2.Text.ToString());            //IP 和 端口
                IPEndPoint ep = new IPEndPoint(broadcast,Convert.ToInt32(textBox3.Text));            //发送信息
                s.SendTo(sendbuf, ep); s.Receive(buf); //应用这种形式来接收服务器的回应。而不是建的UdpClient.