现象
使用Socket建立了TCPServer开启监听后,关闭连接无法成功。
亦或是关闭连接后,二次创建仍显示端口占用问题。
原因以及方法:
①可能是数据流还在传输,导致TCPServer无法关闭。不能直接调用Close()方法。
proxsocket.Close(100);//参数内是允许数据再传输100ms
解决方法:在关闭前,结束全部数据流的传输,再Close,即可成功关闭监听,释放监听端口。
public void StopServerConnet(Socket proxsocket)//关闭连接
{
try
{
proxsocket.Shutdown(SocketShutdown.Both);//禁用某 Socket 上的发送和接收。
}
catch (Exception)
{
}
finally
{
proxsocket.Close(100);
proxsocket.Dispose();
}
}
注意:假如在ShutDonw的时候Catch到了错误,证明禁用失败,已经是其他的问题,此时Close也无济于事。请看原因2。
②在有Client断开连接的时候,Server没有主动去再去断开一次Client。
假如你Server存在一个或多个Client连接,在接收消息方法体内应该监听Client连接情况并且做出相应处理。假如在Client断开时没有做主动断开的处理,就只是结束此方法线程,端口也将无法释放。
错误示范:
var ProxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];//接收消息的缓冲区
while (true)
{
int len = 0;//记录消息长度
try
{
len = ProxSocket.Receive(data, 0, data.Length, SocketFlags.None);//此处接收Client的连接
}
catch (Exception)
{
//假如Client异常退出
return;//让方法结束,终结当前接收服务端数据的异步线程
}
if (len <= 0)
{
//如果小于0,证明无连接,CLient正常退出
return;//让方法结束,终结当前接收服务端数据的异步线程
}
//接收到的消息处理
//…………
}
return;
解决方法:在Client异常退出和正常退出时,都要主动去断开Client的连接,后续监听端口就才能正确释放。
正确示范:
public void ReceiveData(object socket)//TCPServer接收消息的方法
{
var ProxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];//接收消息的缓冲区
while (true)
{
int len = 0;//记录消息长度
try
{
len = ProxSocket.Receive(data, 0, data.Length, SocketFlags.None);//此处接收Client的连接
}
catch (Exception)
{
//假如Client异常退出
//应该关闭此Client连接
ps.StopServerConnet(ProxSocket);
return;//让方法结束,终结当前接收服务端数据的异步线程
}
if (len <= 0)
{
//如果小于0,证明无连接,CLient正常退出
//应该关闭此Client连接
ps.StopServerConnet(ProxSocket);
return;//让方法结束,终结当前接收服务端数据的异步线程
}
//接收到的消息处理
//…………
}
return;
}
关闭Client连接方法与原因①的解决方法一样。
③监听方法开启子线程时没有设置为背景线程,子线程在应用结束时没有结束。
假如在开启监听线程时,只是start,没有设置为背景线程,不仅会阻塞主线程,而且有可能会使应用退出后仍会占用端口。
错误示范:
//1实例化socket类,寻址方式,类型,协议。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
//2实例化端口号
IPEndPoint ip = new IPEndPoint(IPAddress.Any,int.Parse(PortTxt));
//3绑定端口号
try
{
socket.Bind(ip);
//4开启监听
socket.Listen(10);
//5开始接受客户端连接
Thread thread=new Thread(new ParameterizedThreadStart(AcceptClientConnet));//持续监听客户端连接方法
thread.Start(socket);
}
catch (Exception)
{
}
正确示范:文章来源:https://www.toymoban.com/news/detail-418951.html
//1实例化socket类,寻址方式,类型,协议。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
//2实例化端口号
IPEndPoint ip = new IPEndPoint(IPAddress.Any,int.Parse(PortTxt));
//3绑定端口号
try
{
socket.Bind(ip);
//4开启监听
socket.Listen(10);
//5开始接受客户端连接
Thread thread=new Thread(new ParameterizedThreadStart(AcceptClientConnet));//持续监听客户端连接方法
thread.IsBackground=true;//设置为背景线程
thread.Start(socket);
}
catch (Exception)
{
}
总结
无非就是记得关闭数据流,关闭Client连接,设置背景线程。都是细节。细节往往决定成败啊,我被第二个原因卡了几个星期了才发现。希望能帮到大家。文章来源地址https://www.toymoban.com/news/detail-418951.html
到了这里,关于C# 解决Socket/TCPServer监听端口释放失败的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!