使用Socket建立了TCPServer開啟監(jiān)聽后,關(guān)閉連接無法成功。
創(chuàng)新互聯(lián)建站長期為成百上千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為信陽企業(yè)提供專業(yè)的網(wǎng)站設計、網(wǎng)站建設,信陽網(wǎng)站改版等技術(shù)服務。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。亦或是關(guān)閉連接后,二次創(chuàng)建仍顯示端口占用問題。
proxsocket.Close(100);//參數(shù)內(nèi)是允許數(shù)據(jù)再傳輸100ms
解決方法:在關(guān)閉前,結(jié)束全部數(shù)據(jù)流的傳輸,再Close,即可成功關(guān)閉監(jiān)聽,釋放監(jiān)聽端口。
public void StopServerConnet(Socket proxsocket)//關(guān)閉連接
{
try
{
proxsocket.Shutdown(SocketShutdown.Both);//禁用某 Socket 上的發(fā)送和接收。
}
catch (Exception)
{
}
finally
{
proxsocket.Close(100);
proxsocket.Dispose();
}
}
注意:假如在ShutDonw的時候Catch到了錯誤,證明禁用失敗,已經(jīng)是其他的問題,此時Close也無濟于事。請看原因2。
②在有Client斷開連接的時候,Server沒有主動去再去斷開一次Client。假如你Server存在一個或多個Client連接,在接收消息方法體內(nèi)應該監(jiān)聽Client連接情況并且做出相應處理。假如在Client斷開時沒有做主動斷開的處理,就只是結(jié)束此方法線程,端口也將無法釋放。
錯誤示范:
? var ProxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];//接收消息的緩沖區(qū)
while (true)
{
int len = 0;//記錄消息長度
try
{
len = ProxSocket.Receive(data, 0, data.Length, SocketFlags.None);//此處接收Client的連接
}
catch (Exception)
{
//假如Client異常退出
? ? ? ? ? ? return;//讓方法結(jié)束,終結(jié)當前接收服務端數(shù)據(jù)的異步線程
}
if (len<= 0)
{
//如果小于0,證明無連接,CLient正常退出
? ? ? ? ? ? return;//讓方法結(jié)束,終結(jié)當前接收服務端數(shù)據(jù)的異步線程
}
//接收到的消息處理
//…………
}
return;
解決方法:在Client異常退出和正常退出時,都要主動去斷開Client的連接,后續(xù)監(jiān)聽端口就才能正確釋放。
正確示范:
public void ReceiveData(object socket)//TCPServer接收消息的方法
{
var ProxSocket = socket as Socket;
byte[] data = new byte[1024 * 1024];//接收消息的緩沖區(qū)
while (true)
{
int len = 0;//記錄消息長度
try
{
len = ProxSocket.Receive(data, 0, data.Length, SocketFlags.None);//此處接收Client的連接
}
catch (Exception)
{
//假如Client異常退出
? ? ? ? ? ? //應該關(guān)閉此Client連接
ps.StopServerConnet(ProxSocket);
return;//讓方法結(jié)束,終結(jié)當前接收服務端數(shù)據(jù)的異步線程
}
if (len<= 0)
{
//如果小于0,證明無連接,CLient正常退出
//應該關(guān)閉此Client連接
ps.StopServerConnet(ProxSocket);
return;//讓方法結(jié)束,終結(jié)當前接收服務端數(shù)據(jù)的異步線程
}
//接收到的消息處理
? ? ? ? //…………
}
return;
}
關(guān)閉Client連接方法與原因①的解決方法一樣。
③監(jiān)聽方法開啟子線程時沒有設置為背景線程,子線程在應用結(jié)束時沒有結(jié)束。假如在開啟監(jiān)聽線程時,只是start,沒有設置為背景線程,不僅會阻塞主線程,而且有可能會使應用退出后仍會占用端口。
錯誤示范:
//1實例化socket類,尋址方式,類型,協(xié)議。
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開啟監(jiān)聽
socket.Listen(10);
//5開始接受客戶端連接
? ? Thread thread=new Thread(new ParameterizedThreadStart(AcceptClientConnet));//持續(xù)監(jiān)聽客戶端連接方法
thread.Start(socket);
}
catch (Exception)
{
}
正確示范:
//1實例化socket類,尋址方式,類型,協(xié)議。
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開啟監(jiān)聽
socket.Listen(10);
//5開始接受客戶端連接
Thread thread=new Thread(new ParameterizedThreadStart(AcceptClientConnet));//持續(xù)監(jiān)聽客戶端連接方法
? ? thread.IsBackground=true;//設置為背景線程
thread.Start(socket);
}
catch (Exception)
{
}
無非就是記得關(guān)閉數(shù)據(jù)流,關(guān)閉Client連接,設置背景線程。都是細節(jié)。細節(jié)往往決定成敗啊,我被第二個原因卡了幾個星期了才發(fā)現(xiàn)。希望能幫到大家。
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧