C#解决Socket/TCPServer监听端口释放失败的问题-创新互联
现象
原因以及方法: ①可能是数据流还在传输,导致TCPServer无法关闭。不能直接调用Close()方法。
总结
分享文章:C#解决Socket/TCPServer监听端口释放失败的问题-创新互联
本文地址:http://cdiso.cn/article/cecjph.html
使用Socket建立了TCPServer开启监听后,关闭连接无法成功。
创新互联建站长期为成百上千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为信阳企业提供专业的网站设计、网站建设,信阳网站改版等技术服务。拥有十多年丰富建站经验和众多成功案例,为您定制开发。亦或是关闭连接后,二次创建仍显示端口占用问题。
原因以及方法: ①可能是数据流还在传输,导致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)
{
}
正确示范:
//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连接,设置背景线程。都是细节。细节往往决定成败啊,我被第二个原因卡了几个星期了才发现。希望能帮到大家。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
分享文章:C#解决Socket/TCPServer监听端口释放失败的问题-创新互联
本文地址:http://cdiso.cn/article/cecjph.html