我正在编写基于UDP打孔的应用程序。我在客户端之间建立连接时遇到问题。在每个客户端向服务器发送内容并使用其IP与服务器响应之后,客户端无法向对方发送任何内容。我错过了什么吗?或者我对UDP打孔的理解是错误的?是的,我是服务器所在的PC的外部IP。
服务器代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localEP = new IPEndPoint(IP, 80);
UdpClient server = new UdpClient();
server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
server.ExclusiveAddressUse = false;
server.Client.Bind(localEP);
IPEndPoint temp;
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 80);
Console.WriteLine("Dane servera : " + localEP);
byte[] buffer = server.Receive(ref remoteEP);
Console.WriteLine("Otrzymano dane od : " + remoteEP + " o treści " + Encoding.ASCII.GetString(buffer));
temp = remoteEP;
remoteEP = new IPEndPoint(IPAddress.Any, 80);
byte[] buffer2 = server.Receive(ref remoteEP);
Console.WriteLine("Otrzymano dane od : " + remoteEP + " o treści " + Encoding.ASCII.GetString(buffer2));
byte[] response = Encoding.ASCII.GetBytes(temp.ToString());
server.Send(response, response.Length, remoteEP);
byte[] response2 = Encoding.ASCII.GetBytes(remoteEP.ToString());
server.Send(response2, response2.Length,temp );
}
}
}
客户1:
namespace ConsoleApplication1
{
class Program
{
public static IPEndPoint CreateIPEndPoint(string endPoint)
{
string[] ep = endPoint.Split(':');
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
IPAddress ip;
if (ep.Length > 2)
{
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
else
{
if (!IPAddress.TryParse(ep[0], out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
int port;
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
{
throw new FormatException("Invalid port");
}
return new IPEndPoint(ip, port);
}
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localpt = new IPEndPoint(IP, 80);
UdpClient client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
string powitanie = "ASUS";
byte[] buffer = new byte[100];
buffer = Encoding.ASCII.GetBytes(powitanie);
// client.Connect(localpt);
client.Send(buffer, buffer.Length,localpt);
byte[] otrzymane = client.Receive(ref localpt);
Console.WriteLine("Odpowiedz servera : " + Encoding.ASCII.GetString(otrzymane));
Console.Read();
IPEndPoint TV = CreateIPEndPoint(Encoding.ASCII.GetString(otrzymane));
byte[] buffer2 = client.Receive(ref TV);
Console.WriteLine("Odpowiedz klienta : " + Encoding.ASCII.GetString(buffer2));
}
}
}
客户2:
namespace ConsoleApplication1
{
class Program
{
public static IPEndPoint CreateIPEndPoint(string endPoint)
{
string[] ep = endPoint.Split(':');
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
IPAddress ip;
if (ep.Length > 2)
{
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
else
{
if (!IPAddress.TryParse(ep[0], out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
int port;
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
{
throw new FormatException("Invalid port");
}
return new IPEndPoint(ip, port);
}
static void Main(string[] args)
{
IPAddress IP = IPAddress.Parse("xx.xx.xx.xxx");
IPEndPoint localpt = new IPEndPoint(IP, 80);
UdpClient client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
client.ExclusiveAddressUse = false;
string powitanie = "Samsung";
byte[] buffer = new byte[100];
buffer = Encoding.ASCII.GetBytes(powitanie);
// client.Connect(localpt);
client.Send(buffer, buffer.Length,localpt);
byte[] otrzymane = client.Receive(ref localpt);
Console.WriteLine("Odpowiedz servera : " + Encoding.ASCII.GetString(otrzymane));
Console.Read();
IPEndPoint TV = CreateIPEndPoint(Encoding.ASCII.GetString(otrzymane));
client.Send(buffer, buffer.Length, TV);
}
}
}
答案 0 :(得分:0)
如果无法访问您的确切环境和网络,我不相信能够有信心确保解决问题是可能的。但是这里有一些事情要记住:
SocketOptionName.ReuseAddress
,这几乎总是错误的。在我看来,只有你的服务器套接字绑定到一个显式地址,所以使用这个选项可能不会影响测试的结果(即你在任何给定的地址上仍然只有一个套接字,即使你正在测试一台机器)。但是,如果您的测试环境有更多,那么套接字地址确实被重用,这很容易干扰代码的正确操作。最后,您在评论中提问(请在问题本身中提供相关信息和问题):&#34;我应该将udp.connect用于服务器,然后使用udp。在客户之间发送&#34; 。答案是&#34; no&#34;。首先,在UDP套接字上使用Connect()
只是一种方便; UDP本身是无连接的,因此连接UDP套接字完全在框架内处理。第二,在.NET中,当你连接&#34;一个UDP套接字,该框架将过滤数据报,将它们限制为从&#34; connected&#34;端点。这与穿孔打孔完全相反;即您希望能够从服务器和其他客户端接收数据报。