客户端C的内网IP及通讯端口为192.168.1.5:7000,对应的经路由NAT后变为220.120.123.42:15000;服务器S的内网IP及通讯端口为192.168.1.150:9119,对应的路由公网IP为113.93.159.242,已经在路由上做了端口映射。
现在C知道S的公网IP及端口113.93.159.242:9119后,向其发送数据,S能收到C的数据,通过函数function TCustomWSocket.ReceiveFrom(
    Buffer      : Pointer;
    BufferSize  : Integer;
    var From    : TSockAddr;
    var FromLen : Integer) : integer;知道了C的IP和端口为220.120.123.42:15000;然后向C发送确认数据包,但C却收不到任何数据。
此程序我在同一内网中测试时完全正常的。请教大虾们该如何解决呢?

解决方案 »

  1.   

    把你的 收发 代码贴出来   c and s 
      

  2.   

    C的没有,C的只有一个通讯协议。S的接收数据函数procedure TFrmMain.DeviceUDPServerDataAvailable(Sender: TObject;
      ErrCode: Word);
    var
      Buffer:Array[0..SOCKETBUFFERSIZE-1] Of Char;
      Len    : Integer;
      Src    : TSockAddrIn;
      SrcLen : Integer;
      PeerIP:String;
      PeerPort:Integer;
    begin
      //收数据
      SrcLen:=SizeOf(Src);
      ZeroMemory(@Buffer,SOCKETBUFFERSIZE);
      Len:= DeviceUDPServer.ReceiveFrom(@Buffer, SOCKETBUFFERSIZE, Src, SrcLen);
      If Len>0 Then
      Begin
        //得到地址和端口
        PeerIP:=StrPas(inet_ntoa(Src.sin_addr));
        PeerPort:=ntohs(Src.sin_port);
        //处理数据
        If Not ProcessDeviceUDPData(PeerIP,PeerPort,@Buffer,Len) Then
          WriteLogMemo('设备UDP服务处理数据失败:'+StrPas(@Buffer));
        //
      End;
    end;//处理UDP数据
    function TFrmMain.ProcessDeviceUDPData(PeerIP:String;PeerPort:Integer;AData:Pointer;ADataLength:Integer):Boolean;
    var
      UDPSocket:TDeviceSocket;
    Begin
      Result:=False;
      //建立
      UDPSocket:=GetUDPSocket(PeerIP,PeerPort);
      If Not Assigned(UDPSocket) Then
         UDPSocket:=TDeviceSocket.Create(DeviceUDPServer);
         UDPSocket.Addr:=aAddr;
         UDPSocket.Port:=IntToStr(aPort);
         UDPSocket.Proto:='udp';
         UDPSocket.LineMode:=False;
         UDPSocket.LineEdit:=False;
         UDPSocket.Connect;
      If Assigned(UDPSocket) Then
      Begin
        通过适当的填充数据包后进行发送
        UDPSocket.Send(Dest,DestLen);
      End
      Else
      Begin
        WriteLogMemo('建立UDP客户端发生错误!');
      End;
    End;
      

  3.   

     ProcessDeviceUDPData(PeerIP,PeerPort,@Buffer,Len)
    改为 ProcessDeviceUDPData(DeviceUDPServer,PeerIP,PeerPort,@Buffer,Len)
    发送信息回客户端 用DeviceUDPServer 不用另外创建新的 
    DeviceUDPServer.Send(PeerIP,PeerPort,Dest,DestLen);//因该有类似的发送函数吧?
      

  4.   

    你创建新的UPDSocket 新的UDPsocket port 可能就是 5611
    那么 客户端 UPDSocket接收信息时 .ReceiveFrom得到的 port 也就对应 5611
    客户端根据这个port 返回信息给服务器UPDSocket  
    但你服务器负责接收监听的 port 是9119 
    那怎么能接收到数据?同理 客户端 也没有负责接收 来自5611 udpsocket
      

  5.   

    是啊,楼上的有道理啊。我给你提问题:
    220.120.123.42:15000 有没有影射到192.168.1.5:7000?
    如果影射到,你telent试下有什么?请贴出来。 是用telent 220.120.123.42:15000.
    113.93.159.242 的端口是什么? 是9119 吗? 也映射到192.168.1.150:9119吗? 也用telnet试。如果telnet不通,请告诉你用什么做nat的?
    请贴出nat内容。
    如果是linux下的iptable 做的nat, 俺可以看看。。其他俺不懂。
      

  6.   

          找到问题所在了。感谢mhhaifeng同学。你的提醒很有道理。原因是我新建了一个socket来发送数据,如果只用DeviceUDPServer直接发送的没问题了。
          现在我困惑的是为什么在内网中,新建一个socket发送没问题,而放到公网中就不行了呢?难道客户网关只承认一开始建立的连接socket,而继承新建的socket就认定是不安全的连接吗?UDP传输还真的麻烦啊,TCP就没这样的问题。
          而且用 DeviceUDPServer发送时,你还不能直接DeviceUDPServer.Send(Dest,DestLen),这样数据发到客户网关时还会被网关丢掉。必须用DeviceUDPServer.SendTo(Dest:TSockAddr; 
    DestLen : Integer;
    Data: Pointer;
    Len: Integer;
    )  。