一、我的服務器和多客戶端通信有如下特點:
(一)、客戶端(單片機)運行一段時間(大概30秒鐘)將采集的資料傳輸給服務器后,就自己斷電(沒有通知服務器斷開TCP連接)。
1分鐘后,再次上電,運行一段時間(大概30秒鐘)將采集的資料傳輸給服務器后,就自己斷電,客戶端重復回圈上述程序。
(二)、結果我發現,服務器程式內有大量的TCP連接沒有被釋放,系統提示:System.OutOfMemoryException,參見下圖

二、程式如下:
//記錄通信用的Socket
Dictionary<string,Socket> dic = new Dictionary<string, Socket>();
//啟動監聽
private void btnListen_Click(object sender, EventArgs e)
{
btnListen.Enabled = false;
//ip地址
IPAddress ip = IPAddress.Parse(txtIP.Text);
//埠號
IPEndPoint point = new IPEndPoint(ip,int.Parse(txtPort.Text));
TcpListener listen = new TcpListener(point);
listen.Start();
listen.Server.Listen(50);
//創建監聽用的Socket
try
{
ShowMsg("服務器開始監聽");
Thread thread = new Thread(AcceptInfo);
thread.IsBackground = true;
thread.Start(listen);
}
catch (Exception ex)
{
btnListen.Enabled = true;
ShowMsg(ex.Message);
}
}
void AcceptInfo(object o)
{
TcpListener socket = o as TcpListener;
while (true)
{
try
{
//創建通信用的Socket
TcpClient tSocket = socket.AcceptTcpClient();
string point = tSocket.Client.RemoteEndPoint.ToString();
ShowMsg(point + "連接成功!");
dic.Add(point, tSocket.Client); //添加新增加的TCP連接到字典dic
//接收訊息
Thread th = new Thread(ReceiveMsg);
th.IsBackground = true;
th.Start(tSocket);
}
catch (Exception ex)
{
ShowMsg(ex.Message);
break;
}
}
}
//接收訊息
void ReceiveMsg(object o)
{
TcpClient client = o as TcpClient;
while (true)
{
//接收客戶端發送過來的資料
try
{
//定義byte陣列存放從客戶端接收過來的資料
byte[] buffer = new byte[1024 * 1024];
//將接收過來的資料放到buffer中,并回傳實際接受資料的長度
int n = client.Client.Receive(buffer);
if (n == 0)
{
//即便是空資料也不會是0,客戶端不會發送空資料,只能在結束時才有0的可能性
if (client != null)
{
string cpoint = client.Client.RemoteEndPoint.ToString();
if (dic.ContainsKey(cpoint))
dic.Remove(cpoint);
string msg = "客戶端" + cpoint + "下線啦!";
ShowMsg(msg);
client.Close();
}
return;
}
//將位元組轉換成字串
string words = System.Text.Encoding.Default.GetString(buffer, 0, n);
//以下代碼決議TCP報文
catch (Exception ex)
{
if (client != null)
{
string cpoint = client.Client.RemoteEndPoint.ToString();
if (dic.ContainsKey(cpoint))
dic.Remove(cpoint);
string msg = "客戶端" + cpoint + "下線啦!";
ShowMsg(msg);
client.Close();
}
break;
}
}
}
四、我在void ReceiveMsg(object o)的 if (n == 0)和 catch (Exception ex) 2處 都進行檢測,
結果打斷點追蹤發現,當客戶端強行自己斷點,服務器根本檢測不到客戶端TCP連接失效。
五、請問:
1、是因為沒有清除失效的TCP連接導致的System.OutOfMemoryException嗎?
2、當客戶端TCP連接失效,使用client.Close(); 能徹底清除TCP連接占用的記憶體嗎?
3、如何徹底清楚失效的TCP連接占用的記憶體?
uj5u.com熱心網友回復:
你這個TCP有問題。功能簡單。精簡一下代碼即可。監聽有引數不使用TRUE。客戶端接收資訊后。無論是否完成,都要強制關閉連接。
這個時間點你自己把握
uj5u.com熱心網友回復:
我用常規的客戶端軟體進行測驗1、當手動斷開客戶端連接,在void ReceiveMsg(object o)的 if (n == 0) 分支,打斷點追蹤可以檢測到客戶端斷開連接
2、斷開網路,在void ReceiveMsg(object o)的 catch (Exception ex) 處分支,打斷點追蹤可以檢測到連接消失。
但是當我的單片機和服務器TCP連接成功后,單片機突然斷電,服務器死活檢測不到TCP連接消失。
我最關心的問題是:
如何干凈徹底的消除【消失的TCP連接】過多的堆積占用的記憶體空間?
uj5u.com熱心網友回復:
要做心跳啊,沒心跳就關掉。
uj5u.com熱心網友回復:
我是菜鳥,請問:是否關閉了失效的TCP連接就可以釋放該連接占用的記憶體空間了呢?
即執行:client.Close(); 即可以釋放該連接占用的記憶體空間了呢?
uj5u.com熱心網友回復:
是的,關閉并從你的字典中移除,就會被GC回收釋放。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/119192.html
標籤:C#
上一篇:c# 畫圖
