C#UDP数据包中继器:重新启动将不起作用
长话短说:我需要一个UDP数据包转发器/重发器。 它应该做什么? 嗯,它应该在特定的端口上侦听输入的数据包,然后在指定的端口上将它们发回。 该程序有一个GUI,其中一个按钮用于运行和关闭程序 这个程序运行得很好,直到我开始。。。好吧,去他妈的 慢慢地,我设法把大部分虫子都弄出来了。除了一个。。。或更多: 问题是,如果我想重新启动程序,通过单击按钮,我在上面的链接中得到了相同的错误 我曾尝试实现Shutdown()、Dispose()、Disconnect()、UDP_Client=null以及我用谷歌搜索过的更多功能,但它要么生成了新错误,要么没有效果C#UDP数据包中继器:重新启动将不起作用,c#,multithreading,visual-studio,error-handling,C#,Multithreading,Visual Studio,Error Handling,长话短说:我需要一个UDP数据包转发器/重发器。 它应该做什么? 嗯,它应该在特定的端口上侦听输入的数据包,然后在指定的端口上将它们发回。 该程序有一个GUI,其中一个按钮用于运行和关闭程序 这个程序运行得很好,直到我开始。。。好吧,去他妈的 慢慢地,我设法把大部分虫子都弄出来了。除了一个。。。或更多: 问题是,如果我想重新启动程序,通过单击按钮,我在上面的链接中得到了相同的错误 我曾尝试实现Shutdown()、Dispose()、Disconnect()、UDP_Client=null以及
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Packet_Repeater
{
public partial class Form1 : Form
{
public bool connection_status = false;
UdpClient[] UDP_Client;
IPEndPoint[] IP_End_Point;
IPAddress[][] IP_Address;
Thread[] Task;
public int[] upd_client_src_port, udp_client_dst_port;
public bool[] packet_rxd;
public bool[] task_running;
public byte[][] BUFFER;
public int[,] UDP_Client_num;
public Form1()
{
InitializeComponent();
}
public void Init_Size(int num)
{
UDP_Client = new UdpClient[num];
IP_End_Point = new IPEndPoint[num];
IP_Address = new IPAddress[num][];
Task = new Thread[num];
upd_client_src_port = new int[num];
udp_client_dst_port = new int[num];
packet_rxd = new bool[num];
BUFFER = new byte[num][];
UDP_Client_num = new int[num,2];
task_running = new bool[num];
}
public void UDP_Init(int client_num, string target_ip, int src_port, int dst_port)
{
upd_client_src_port[client_num] = src_port;
udp_client_dst_port[client_num] = dst_port;
BUFFER[client_num] = new byte[1536];
if(target_ip == "Any")
{
IP_End_Point[client_num] = new IPEndPoint(IPAddress.Any, udp_client_dst_port[client_num]);
}
else
{
IP_Address[client_num] = Dns.GetHostAddresses(target_ip);
IP_End_Point[client_num] = new IPEndPoint(IP_Address[client_num][0], udp_client_dst_port[client_num]);
}
UDP_Client[client_num] = new UdpClient(upd_client_src_port[client_num]);
UDP_Client[client_num].Client.SendTimeout = 500;
UDP_Client[client_num].Client.ReceiveTimeout = 500;
}
public void Run_Client(int listner_client_num, int destination_client_num)
{
task_running[listner_client_num] = true;
while (connection_status)
{
try
{
BUFFER[listner_client_num] = UDP_Client[listner_client_num].Receive(ref IP_End_Point[listner_client_num]);
UDP_Client[destination_client_num].Send(BUFFER[listner_client_num], BUFFER[listner_client_num].Length, IP_End_Point[destination_client_num]);
}
catch (Exception) { }
}
Array.Clear(BUFFER[listner_client_num], 0, BUFFER[listner_client_num].Length);
// Thread.Sleep(10000);
UDP_Client[listner_client_num].Close();
task_running[listner_client_num] = false;
}
public void button_Click(object sender, EventArgs e)
{
int number_of_connections = 2;
if(!connection_status)
{
button.Enabled = false;
connection_status = true;
Init_Size(number_of_connections);
UDP_Client_num[0, 0] = 0;
UDP_Client_num[0, 1] = 1;
UDP_Client_num[1, 0] = 1;
UDP_Client_num[1, 1] = 0;
UDP_Init(0, "Any", 9700, 9701);
UDP_Init(1, "Any", 9600, 9601);
// the Problem is in this for() cycle
for (UInt32 i = 0; i < (number_of_connections-1); i++)
{
Task[i] = new Thread(ThreadStart => Run_Client(UDP_Client_num[i, 0], UDP_Client_num[i, 1]));
Task[i].Start();
}
/* This works OK:
myTask[0] = new Thread(ThreadStart => Run_Client(UDP_Client_num[0, 0], UDP_Client_num[0, 1]));
myTask[0].Start();
myTask[1] = new Thread(ThreadStart => Run_Client(UDP_Client_num[1, 0], UDP_Client_num[1, 1]));
myTask[1].Start();
*/
button.Text = "Close";
button.Enabled = true;
}
else
{
connection_status = false;
button.Enabled = false;
for (int i = 0; i < (number_of_connections-1);)
{
if(!task_running[i])
{
i++;
}
}
button.Text = "Run";
button.Enabled = true;
}
}
}
}
这帮助我发现,恩德的一个克林特根本没有关闭。
因此,我在beggining和Run_Client()的末尾添加了一个write to textbox函数。
由于某些原因,一个任务[]无法启动。因此,这是一个线程问题,而不是NetSocket。问题和解决方案非常简单。由于某种原因,这一行出现了线程问题:
for (int i = 0; i < (number_of_connections); i++)
{
Task[i] = new Thread(ThreadStart => Run_Client(UDP_Client_num[i, 0], UDP_Client_num[i, 1]));
Task[i].Start();
while(!task_running[i])// <<-- This is probably a better Solution
{
Thread.Sleep(1);
}
// Thread.Sleep(100); // <<-- This Solved the Problem
}
这向我显示了所有正在使用的udp端口
解决方案是在for()循环中将主线程设置为睡眠一段时间。我已将其设置为100ms,但maybee less也可以。(尚未尝试过。)请参阅网页:。连接有3项。1) 来源IP。2) 目标IP。3) 端口号。不能有多个连接同时连接所有三个项目。这就是造成错误的原因。使用多播侦听器,查看您的链接,您可以与PC建立一个虚拟连接,并在PC上创建一个端点,该端点称为IPAddressAny。PC上只有一个应用程序可以使用相同的端口号连接到IPAnyAddress。使用多播,您不需要完全连接,因为它是广播类型的消息。相反,你加入了一个团体。所以你说我在正确的轨道上?问题是,我的程序尝试重新创建具有相同IP/端口配置的UDP客户端,与以前一样。这不是我的本意。我想通过第二次单击按钮关闭所有UDP客户端,并在关闭应用程序时释放所有端口。通过第三次单击该按钮,它应该可以使用以前发布的IP/端口重新创建所有UDP客户端,而不会出现问题。这就是我想要做的。在代码中的某个地方,您试图打开一个已经打开的连接。可能是在打开新连接时打开了同一个客户端两次,或者是没有正确关闭连接。如果您有两个udp客户端侦听相同的端口号(广播),则必须使用加入组。问题肯定是未关闭的客户端。我使用了这个cmd netstat-a-b-n-pdp-o,并看到端口9700保持打开状态。所以一个Close()被跳过或失败。我找不到它,你必须这样做。向代码中添加一些调试语句以找出根本原因。Thread.Sleep不应用于修复线程问题,因为无法保证所需的睡眠时间。与其使用线程,不如考虑使用与AcYNC/AWED关键字相结合的任务,并研究为什么延迟会解决问题,而不是修补问题。我已经把线程放在一个WHEELY()循环中,检查任务[I]是否已经运行。如果它没有运行,main()代码将一次又一次地等待(进入睡眠状态1毫秒),直到任务[i]运行。这是一种更好的方法吗?您可以在这里使用互斥体/信号量/信令机制来通信任务是否已启动。
for (int i = 0; i < (number_of_connections); i++)
{
Task[i] = new Thread(ThreadStart => Run_Client(UDP_Client_num[i, 0], UDP_Client_num[i, 1]));
Task[i].Start();
while(!task_running[i])// <<-- This is probably a better Solution
{
Thread.Sleep(1);
}
// Thread.Sleep(100); // <<-- This Solved the Problem
}
netstat -a -n -p udp -o