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
相关产品推荐
相关产品推荐

