You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS UDP服务器无法向家庭客户端回传响应的排查求助

UDP远程通信回传失败问题排查建议

问题背景

我用C# UDP Socket搭建了部署在AWS的服务器与家庭客户端的通信,基于GitHub的UDPSocket.cs示例修改代码,实现服务器接收客户端首条消息后回传响应。目前客户端可成功向AWS服务器发送消息,但服务器调用SendTo回传的消息无法被客户端接收;此前曾出现“connection refused”错误,现在无报错但无响应。AWS服务器已允许所有出站流量,禁止27000端口入站(注:实际应为允许27000端口入站,否则客户端无法发送消息)。本地两台机器测试时功能完全正常,仅远程通信时存在回传问题。

客户端代码

public void Client(string address, int port)
{
    _socket.Connect(IPAddress.Parse(address), port);
    Receive();            
}

public void Send(string text)
{
    byte[] data = Encoding.ASCII.GetBytes(text);
    _socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
    {
        State so = (State)ar.AsyncState;
        int bytes = _socket.EndSend(ar);
        Console.WriteLine("SEND: {0}, {1}", bytes, text);
    }, state);
}

public void Receive()
{
    _socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
    {
        State so = (State)ar.AsyncState;
        int bytes = _socket.EndReceiveFrom(ar, ref epFrom);
        _socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
        Console.WriteLine("RECV: {0}: {1}, {2}", epFrom.ToString(), bytes, Encoding.ASCII.GetString(so.buffer, 0, bytes));
    }, state);
}

int port = 27000;

UDPSocket c = new UDPSocket();

int new_port = 40156;
IPEndPoint bep = new IPEndPoint(IPAddress.Parse([MY_HOME_INTERNAL_IP]), new_port );
if( bep != null ){
    Console.WriteLine("binding_to_ep");
    c._socket.Bind( bep );
    c.Receive();
}

c.Client([REMOTE_SERVER_EXTERNAL_IP], port );
c.Send("TEST!");
Console.ReadKey();

服务器代码

public void Server(string address, int port)
{
    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
    _socket.Bind(new IPEndPoint(IPAddress.Parse(address), port));
    Receive();
}


private void Receive()
{
    _socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
    {
        State so = (State)ar.AsyncState;
        int bytes = _socket.EndReceiveFrom(ar, ref epFrom);
        _socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
        Console.WriteLine("RECV: {0}: {1}, {2}", epFrom.ToString(), bytes, Encoding.ASCII.GetString(so.buffer, 0, bytes));

        //尝试回传消息,但客户端无接收
        byte[] data = Encoding.ASCII.GetBytes("12");
        //EndPoint epFrom1 = new IPEndPoint(IPAddress.Parse( [MY_HOME_EXTERNAL_IP] ), 40156);
        EndPoint epFrom1 = new IPEndPoint(IPAddress.Parse([MY_HOME_EXTERNAL_IP]), 27000 );
        _socket.SendTo(data, epFrom1 );
    }, state);
}

UDPSocket s = new UDPSocket();
s.Server( [THE_SERVER_LOCAL_IP] , port );

解决建议

  • 不要硬编码客户端回传地址:服务器收到客户端消息时,epFrom已经包含了客户端的公网IP和NAT映射后的实际端口(不是客户端绑定的40156),直接使用这个epFrom调用SendTo回传即可,无需手动创建新的IPEndPoint。硬编码的端口大概率和NAT实际映射的端口不匹配,导致消息无法到达。
  • 调整客户端绑定逻辑:客户端无需手动绑定内部IP和固定端口,去掉c._socket.Bind(bep)这部分代码,让系统自动分配端口。手动绑定内部IP会导致Socket仅监听内部网络流量,无法接收来自公网的回传消息;同时自动分配端口能让NAT正确建立会话映射,服务器回传的消息可以通过NAT转发到客户端。
  • 配置家庭路由器端口转发:如果必须使用固定端口,需要在家庭路由器上设置端口转发规则,将公网的40156端口(或其他端口)映射到客户端内部IP的40156端口,确保服务器回传的消息能通过NAT转发到客户端。
  • 确认AWS安全组规则:确保AWS服务器的安全组入站规则允许UDP 27000端口(否则客户端无法发送消息到服务器),出站规则已经允许所有流量,这部分可再次验证。
  • 抓包调试:在客户端用Wireshark抓包,查看是否收到服务器的回传数据包;在服务器打印epFrom的具体值,确认回传的目标地址和端口是否正确。

内容的提问来源于stack exchange,提问作者Mat Edor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:19:50