我有以下UDP服务器侦听端口11000:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPServer
{
class Program
{
static byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };
// get the ip and port number where the client will be listening on
static IPEndPoint GetClientInfo()
{
// wait for client to send data
using (UdpClient listener = new UdpClient(11000))
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
return groupEP;
}
}
static void Main(string[] args)
{
var info = GetClientInfo(); // get client info
/* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
*/
// create a new client. this client will be created on a
// different computer when I do readl udp punch holing
UdpClient newClient = ConstructUdpClient(info);
// send data
newClient.Send(dataToSend, dataToSend.Length);
}
// Construct a socket with the info received from the client
static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
{
var ip = clientInfo.Address.ToString();
var port = clientInfo.Port;
// this is the part I was missing!!!!
// the local end point must match. this should be the ip this computer is listening on
// and also the port
UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 11000));
// lastly we are missing to set the end points. (ip and port client is listening on)
// the connect method sets the remote endpoints
client.Connect(ip, port);
return client;
}
}
我也在路由器中打开了一个端口,所以当从路由器的网关地址收到数据时,它将映射到我的主机上192.168.1.101:1000,如下所示:
我还定义了以下客户端,它在LAN上的另一台计算机(192.168.1.108)上运行:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace UDPClient
{
class Program
{
static void Main(string[] args)
{
string ipOfServer = "205.172.111.250";
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- we can receive data now!!!!!
}
}
}
请注意ipOfServer。这是我的外部网关(不是因为我对它进行了混淆,但它不是192.168.1.101 - 我的UDP服务器的内部IP)。
当我指示客户端发送到内部LAN IP为192.168.1.101:11000时,UDP服务器会连接。
但是,当我使用网关的IP地址和端口时,UDP服务器无法连接。由于我在NAT中将端口指向192.168.1.101:1000,因此我不确定是什么。
我知道NAT设置很好,因为我的HTTP端口80和net.tcp的端口808都可以在任何地方工作,甚至在我的网络之外。
请告诉我一些关于我做错的事情。
亲切的问候
答案 0 :(得分:1)
如果没有访问您的实际网络设置,很难确切地知道错误。但是,创建套接字的方案只是为了接收一些被丢弃的数据,然后才创建一个新的套接字,然后你就可以连接&#34;对客户来说,似乎错了。你可能不应该首先使用带有UDP套接字的Connect()
,如果你觉得必须,你应该在收到一些数据后连接原始套接字。
无论如何,它确实是你需要担心的事情的客户方面。您已设置路由器以转发服务器的入站数据报,因此服务器应始终能够在该端口上接收。这是有问题的客户的回传流量;事实上,并非所有路由器都支持这种情况,并且总是需要端口转发UDP流量(TCP流量更容易,因为路由器可以与客户端保持连接)。
我建议您使服务器更简单 - 只需创建一个用于接收数据报的套接字(因此当然不要将其与using
一起配置)。我还建议不要使用Connect()
,因为所做的一切都会不必要地限制服务器。即它将阻止服务器的套接字能够处理多个客户端。如果你真的想做一些每个客户端的过滤,一个更好的机制是服务器总是接收所有数据报,然后检查接收地址本身以决定如何处理数据报。