Zac*_*ach 5 c# sockets port tcp client-server
我正在做一个简单的项目,涉及单个服务器程序和单个客户端程序。它需要检查客户端是否已连接(从服务器端),反之亦然。
当客户端失去互联网时,服务器需要知道它已断开连接。然后,客户端需要在重新连接互联网时重新连接到服务器
当客户端失去互联网然后重新获得互联网时,我无法使用相同的端口重新连接。
我尝试让服务器监听而不关闭套接字,但这也不起作用。在重用方面,我为套接字尝试了很多属性,我也尝试了挥之不去的东西。
我已经看到它可能会停留在TIME_WAIT
操作系统在注册表中设置的某些属性上(在 Windows 的情况下)。重申一下,我的问题是能够使用相同的套接字(更重要的是相同的端口)在客户端丢失并重新获得互联网后重新连接,并且仍在监听等待重新连接。
就像我说的,我可以检测到它何时与服务器端和客户端断开连接,但是当我尝试使用相同的端口和相同的套接字或重新启动的套接字重新连接时,它仍然无法连接,也不会出现在所有。有什么建议可以帮助解决这个问题吗?我一直在寻找很长时间才能弄清楚这个问题。
设想:
TL;DR 在客户端 - 服务器模型上丢失并重新获得互联网,但无法使用相同的套接字和端口连接到服务器。
private void button2_Click(object sender, EventArgs e)
{
// This will stop the threads/connections and toggle the button back to its original state
if (button2.Text == "Stop Listening")
{
listener.Close();
stop = true;
threadsActive = false;
button2.Text = "Start Listening";
textBox1.AppendText("Manually Closed Threads/Connections" + Environment.NewLine);
}
else
{
listenThread = new Thread(listenLoop);
listenThread.IsBackground = true;
status = new Thread(checkIfOnline);
status.IsBackground = true;
stop = false;
threadsActive = true;
button2.Text = "Stop Listening";
localEndPoint = new IPEndPoint(IPAddress.Parse("129.59.79.65"), 3000);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenThread.Start();
status.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
================================================== ==
private void listenLoop()
{
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
textBox1.AppendText("Waiting for a client..." + Environment.NewLine);
listener = listener.Accept();
textBox1.AppendText("Client Connected!!" + Environment.NewLine);
status.Start();
while (!close)
{
if (stop)
return;
// server connection loop
}
if(close)
return;
}
catch (Exception excp)
{
}
}
Run Code Online (Sandbox Code Playgroud)
================================================== ==
private void ResetSocket()
{
// stop all threads and connections
stop = true;
listener.Close();
textBox1.AppendText("Attempting to kill threads..." + Environment.NewLine);
//while (listenThread.IsAlive == true || status.IsAlive == true) { /*loop until the threads are killed*/ textBox1.AppendText("Closing Threads..."); }
//listener.Close();
threadsActive = false;
textBox1.AppendText("All Threads/Connections Closed" + Environment.NewLine + "Restarting Threads/Connections..." + Environment.NewLine);
// re-establish and start threads and connections again
stop = false;
listenThread = new Thread(listenLoop);
listenThread.IsBackground = true;
status = new Thread(checkIfOnline);
status.IsBackground = true;
threadsActive = true;
localEndPoint = new IPEndPoint(IPAddress.Parse("129.59.79.65"), 3000);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenThread.Start();
status.Start();
textBox1.AppendText("Threads/Connections Restarted Successfully" + Environment.NewLine);
}
Run Code Online (Sandbox Code Playgroud)
不要绑定客户端套接字。只有服务器端口很重要。
在服务器端,只需保持监听套接字监听即可。当监听套接字接受连接时,它返回一个代表该连接的新套接字。当检测到连接丢失时,关闭相应的连接套接字,但保持侦听套接字运行。
顺便说一句,IMO 检测连接丢失的最佳方法是定期发送数据(双向)。
我的博客上有TCP/IP .NET 常见问题解答。它是 .NET,但一般概念适用于任何 TCP/IP 场景。