c# UDP 问题 【在线】 按道理来说symmetic NAT 后的机器只要先给SERVER 发包,SERVER 收到后立刻回包应该和Client1是能够通讯上的. 不知道你的为什么?是不是你NAT后有多于1个的公网IP? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 对于symmetic NAT, 打开的端口会变化, 也就是在symmetic NAT 后的机器A给Server发送包后,symmetic NAT打开的端口就会改变,所以此时外网发送到这端口的包就会被丢弃。在这种NAT上建立P2P通讯是很困难的。有的说用端口猜测, 但也不容易成功。 不会吧,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通信。 不知道楼主是如何回复侦听信息的,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{}} 我贴下代码,先贴服务器的这个运行在服务器上,有外网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);//发送信息 } 这个是客户端向服务器发报(服务器可以收到) 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()); } 嗯,习惯思维,当成两个是在内肉了。分析楼主的代码:你是向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. string.Format中char[]不能做参数数组??? (Joomla)PHP一点没接触过,现在有问题。麻烦进来帮一下,会不会是另一回事。 c#学习方法问题 如何递归实现一个对象的序列化 [求救]Vss如何管理更新Dll??? C# 使用第三方控件——ATGrid报表控件示例 comboBox显示问题 WIN CE 键盘钩子 hHookKey 值一直为 0 C#引用OCK控件的问题 <asp.net编程精彩百例>源代码 求一个WINFORMS登陆窗体的代码 要求连接到数据库.! stringBuilder,加密,字符串替换,
在这种NAT上建立P2P通讯是很困难的。有的说用端口猜测, 但也不容易成功。
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通信。
服务器侦听这样:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket类 Socket c = null;
while (true) {
try
{
c = sock .Accept();
//这个c 发来信息后,就可以给客户端回复信息了,如果需要一直使用,可用一个实例保存这个SOCKET,这个SOCKET就是你和客户端通讯的东西喽!
//信息接收完成后,再继续开始一个侦听,然后跳出循环
}
catch
{}
}
这个运行在服务器上,有外网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);//发送信息
}
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());
}
分析楼主的代码:你是向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.