目錄
- 簡介
- 使用方法
- 實作客戶端
- 實作服務端
- 總結
簡介
作業中經常遇到需要實作TCP客戶端或服務端的時候,如果每次都自己寫會很麻煩且無聊,使用SuperSocket庫又太大了,這時候就可以使用SimpleTCP了,當然僅限于C#語言,
SimpleTCP是一個簡單且非常有用的 .NET 庫,用于處理啟動和使用 TCP 套接字(客戶端和服務器)的重復性任務,使用起來非常方便、代碼也少,它的內部不是直接使用的Socket,而是在TcpClient的基礎上進行了再次封裝,介面更簡單、明了,
它的主要特點如下:
- 原始碼簡單:原始碼就幾個類,每個類也不大,在了解TcpClient用法的基礎上不需要注釋就可以看懂,
- 功能單一:不像其它庫一樣功能繁多,它只專注于實作簡單的TCP客戶端、服務端,使用起來不用擔心增加系統的復雜性,
- 使用簡單:后面的示例會具體講解,啟動一個客戶端或服務端只需要幾行代碼,想擴展功能也很簡單,
說一下它的不足之處(在我看來完全可以接受):
- 已停止更新:最后更新時間是2017年,不過庫的功能比較簡單、單一,也沒那么多更新的內容,
- 性能不是最優的:底層是基于TcpClient的,性能注定不會太高,但能用TcpClient的地方都可以用它,
使用方法
在專案中直接參考SimpleTCP.dll即可, dll檔案可以通過NuGet安裝或從github下載原始碼編譯,
SimpleTCP內部有一個特殊字符分割字串的協議可以直接使用,也可以在DataReceived事件處理程式中實作自己的協議,
實作客戶端
實作一個客戶端的代碼如下:
//初始化
var client = new SimpleTcpClient();
//設定編碼格式,默認是UTF8
client.StringEncoder = System.Text.ASCIIEncoding.ASCII;
//設定分隔符,默認是0x13
client.Delimiter = Encoding.ASCII.GetBytes("\r")[0];
//收到分割資料的事件,遇到分隔符就會觸發事件
client.DelimiterDataReceived += (sender, msg) =>
{
Console.WriteLine("DelimiterStr-"+DateTime.Now.ToString()+ msg.MessageString);
};
//收到資料的事件,可以在這里實作自己的協議
client.DataReceived += (sender, msg) =>
{
//位元組陣列
Console.WriteLine("Data:"+BitConverter.ToString(msg.Data));
//字串訊息
Console.WriteLine("ReceivedStr:" + msg.MessageString);
};
DelimiterDataReceived和DataReceived內部使用了兩個不同的位元組鏈表,決議起來互不影響,這兩個事件的處理程式中盡量不要做耗時的操作,否則會影響后續的資料接收,
SimpleTCP沒有心跳、重連功能,也沒找到反饋客戶端連接狀態的屬性(不建議使用內部TcpClient的連接狀態),我們可以直接擴展這些功能,代碼如下:
bool exit = false;
bool connected = false;
Task.Factory.StartNew(() =>
{
while (!exit)
{
try
{
if (connected)
{
//發送心跳
client.Write("");
Task.Delay(10000).Wait();
}
else
{
//斷線重連
client.Connect("127.0.0.1", 4196);
connected = true;
Task.Delay(1000).Wait();
}
}
catch (Exception)
{
connected = false;
client.Disconnect();
}
}
}, TaskCreationOptions.LongRunning);
把上面的代碼按順序復制到控制臺的Main函式中,然后加入下面的代碼就可以收發資料了:
while (true)
{
string strLine = Console.ReadLine();
if (strLine == "esc")
{
exit = true;
client.Disconnect();
return;
}
if (connected)
{
//獲取服務端回復的訊息,最多等待3秒,收到訊息時會提前回傳
//也可以使用Write、WriteLine方法發送資料,WriteLine會自動在后面加上設定的分隔符
var replyMsg = client.WriteLineAndGetReply(strLine, TimeSpan.FromSeconds(3));
if (replyMsg != null)
{
Console.WriteLine(replyMsg);
}
}
}
注:WriteLineAndGetReply內部使用的是DataReceived,不會自動去除分隔符,
實作服務端
服務端功能比較簡單,把收到分割資料加工后回傳客戶端,代碼如下:
//初始化
var server = new SimpleTcpServer();
//設定編碼格式,默認是UTF8
server.StringEncoder = System.Text.ASCIIEncoding.ASCII;
server.Delimiter = Encoding.ASCII.GetBytes("\r")[0];
//分割資料接收事件
server.DelimiterDataReceived += (sender, msg) =>
{
Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString()+":" + msg.MessageString);
msg.ReplyLine("Reply-" + msg.MessageString);
};
//資料接收資料
server.DataReceived += (sender, msg) =>
{
Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString() + ":" + msg.MessageString);
};
//客戶端連接事件
server.ClientConnected += (sender, msg) =>
{
Console.WriteLine("ClientConnected:" + msg.Client.RemoteEndPoint.ToString());
};
//客戶端斷開事件
server.ClientDisconnected += (sender, msg) =>
{
Console.WriteLine("ClientDisconnected:" + msg.Client.RemoteEndPoint.ToString());
};
//開始監聽
server.Start(4196);
//監聽的IP
var listeningIps = server.GetListeningIPs();
//監聽的V4Ip
var listeningV4Ips = server.GetListeningIPs().Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
Task.Factory.StartNew(() =>
{
while (true)
{
//連接數監控
int clientsConnected = server.ConnectedClientsCount;
Console.WriteLine("當前連接的客戶端數:" + clientsConnected);
Task.Delay(10000).Wait();
}
}, TaskCreationOptions.LongRunning);
Console.ReadLine();
//停止監聽
server.Stop();
Console.WriteLine("停止服務端!");
Console.ReadLine();
總結
上面的代碼主要為了展示庫的功能,實際使用時可能就幾行代碼,性能要求不高的專案都可以使用,
專案和庫的原始碼鏈接如下:
- TcpTest 提取碼:wvj0
- SimpleTCP-master.zip 提取碼:kycj(推薦在github上下載)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/299547.html
標籤:C#
下一篇:C#開源類別庫SimpleTCP
