C#開源類庫SimpleTCP使用方法
簡介
工作中經(jīng)常遇到需要實(shí)現(xiàn)TCP客戶端或服務(wù)端的時(shí)候,如果每次都自己寫會(huì)很麻煩且無聊,使用SuperSocket庫又太大了。這時(shí)候就可以使用SimpleTCP了,當(dāng)然僅限于C#語言。
SimpleTCP是一個(gè)簡單且非常有用的 .NET 庫,用于處理啟動(dòng)和使用 TCP 套接字(客戶端和服務(wù)器)的重復(fù)性任務(wù),使用起來非常方便、代碼也少。它的內(nèi)部不是直接使用的Socket,而是在TcpClient的基礎(chǔ)上進(jìn)行了再次封裝,接口更簡單、明了。
它的主要特點(diǎn)如下:
- 源碼簡單:源碼就幾個(gè)類,每個(gè)類也不大,在了解TcpClient用法的基礎(chǔ)上不需要注釋就可以看懂。
- 功能單一:不像其它庫一樣功能繁多,它只專注于實(shí)現(xiàn)簡單的TCP客戶端、服務(wù)端,使用起來不用擔(dān)心增加系統(tǒng)的復(fù)雜性。
- 使用簡單:后面的示例會(huì)具體講解,啟動(dòng)一個(gè)客戶端或服務(wù)端只需要幾行代碼,想擴(kuò)展功能也很簡單。
說一下它的不足之處(在我看來完全可以接受):
- 已停止更新:最后更新時(shí)間是2017年,不過庫的功能比較簡單、單一,也沒那么多更新的內(nèi)容。
- 性能不是最優(yōu)的:底層是基于TcpClient的,性能注定不會(huì)太高,但能用TcpClient的地方都可以用它。
使用方法
在項(xiàng)目中直接引用SimpleTCP.dll即可, dll文件可以通過NuGet安裝或從github下載源碼編譯。
SimpleTCP內(nèi)部有一個(gè)特殊字符分割字符串的協(xié)議可以直接使用,也可以在DataReceived事件處理程序中實(shí)現(xiàn)自己的協(xié)議。
實(shí)現(xiàn)客戶端
實(shí)現(xiàn)一個(gè)客戶端的代碼如下:
//初始化 var client = new SimpleTcpClient(); //設(shè)置編碼格式,默認(rèn)是UTF8 client.StringEncoder = System.Text.ASCIIEncoding.ASCII; //設(shè)置分隔符,默認(rèn)是0x13 client.Delimiter = Encoding.ASCII.GetBytes("\r")[0]; //收到分割數(shù)據(jù)的事件,遇到分隔符就會(huì)觸發(fā)事件 client.DelimiterDataReceived += (sender, msg) => { Console.WriteLine("DelimiterStr-"+DateTime.Now.ToString()+ msg.MessageString); }; //收到數(shù)據(jù)的事件,可以在這里實(shí)現(xiàn)自己的協(xié)議 client.DataReceived += (sender, msg) => { //字節(jié)數(shù)組 Console.WriteLine("Data:"+BitConverter.ToString(msg.Data)); //字符串消息 Console.WriteLine("ReceivedStr:" + msg.MessageString); };
DelimiterDataReceived和DataReceived內(nèi)部使用了兩個(gè)不同的字節(jié)鏈表,解析起來互不影響。這兩個(gè)事件的處理程序中盡量不要做耗時(shí)的操作,否則會(huì)影響后續(xù)的數(shù)據(jù)接收。
SimpleTCP沒有心跳、重連功能,也沒找到反饋客戶端連接狀態(tài)的屬性(不建議使用內(nèi)部TcpClient的連接狀態(tài))。我們可以直接擴(kuò)展這些功能,代碼如下:
bool exit = false; bool connected = false; Task.Factory.StartNew(() => { while (!exit) { try { if (connected) { //發(fā)送心跳 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);
把上面的代碼按順序復(fù)制到控制臺(tái)的Main函數(shù)中,然后加入下面的代碼就可以收發(fā)數(shù)據(jù)了:
while (true) { string strLine = Console.ReadLine(); if (strLine == "esc") { exit = true; client.Disconnect(); return; } if (connected) { //獲取服務(wù)端回復(fù)的消息,最多等待3秒,收到消息時(shí)會(huì)提前返回 //也可以使用Write、WriteLine方法發(fā)送數(shù)據(jù),WriteLine會(huì)自動(dòng)在后面加上設(shè)置的分隔符 var replyMsg = client.WriteLineAndGetReply(strLine, TimeSpan.FromSeconds(3)); if (replyMsg != null) { Console.WriteLine(replyMsg); } } }
注:WriteLineAndGetReply內(nèi)部使用的是DataReceived,不會(huì)自動(dòng)去除分隔符。
實(shí)現(xiàn)服務(wù)端
服務(wù)端功能比較簡單,把收到分割數(shù)據(jù)加工后返回客戶端,代碼如下:
//初始化 var server = new SimpleTcpServer(); //設(shè)置編碼格式,默認(rèn)是UTF8 server.StringEncoder = System.Text.ASCIIEncoding.ASCII; server.Delimiter = Encoding.ASCII.GetBytes("\r")[0]; //分割數(shù)據(jù)接收事件 server.DelimiterDataReceived += (sender, msg) => { Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString()+":" + msg.MessageString); msg.ReplyLine("Reply-" + msg.MessageString); }; //數(shù)據(jù)接收數(shù)據(jù) 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()); }; //開始監(jiān)聽 server.Start(4196); //監(jiān)聽的IP var listeningIps = server.GetListeningIPs(); //監(jiān)聽的V4Ip var listeningV4Ips = server.GetListeningIPs().Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork); Task.Factory.StartNew(() => { while (true) { //連接數(shù)監(jiān)控 int clientsConnected = server.ConnectedClientsCount; Console.WriteLine("當(dāng)前連接的客戶端數(shù):" + clientsConnected); Task.Delay(10000).Wait(); } }, TaskCreationOptions.LongRunning); Console.ReadLine(); //停止監(jiān)聽 server.Stop(); Console.WriteLine("停止服務(wù)端!"); Console.ReadLine();
總結(jié)
上面的代碼主要為了展示庫的功能,實(shí)際使用時(shí)可能就幾行代碼,性能要求不高的項(xiàng)目都可以使用。
項(xiàng)目和庫的源碼鏈接如下:
鏈接: https://pan.baidu.com/s/1NgW4CQsU-1BJGgJHg8X2Fg 提取碼: 7vgf
鏈接: https://pan.baidu.com/s/1_2Gr83mkygHdN6B3KIx56w 提取碼: 5kdh
到此這篇關(guān)于C#開源類庫SimpleTCP的文章就介紹到這了,更多相關(guān)C#開源類庫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MFC實(shí)現(xiàn)學(xué)生選課系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了MFC實(shí)現(xiàn)學(xué)生選課系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02利用QDir實(shí)現(xiàn)刪除選定文件目錄下的空文件夾
這篇文章主要為大家詳細(xì)介紹了如何利用QDir實(shí)現(xiàn)刪除選定文件目錄下的空文件夾功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下2022-08-08C++實(shí)現(xiàn)循環(huán)隊(duì)列和鏈?zhǔn)疥?duì)列的示例
下面小編就為大家分享一篇C++實(shí)現(xiàn)循環(huán)隊(duì)列和鏈?zhǔn)疥?duì)列的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12C++ OpenCV模擬實(shí)現(xiàn)微信跳一跳
這篇文章主要介紹了使用C++和OpenCV模擬實(shí)現(xiàn)微信跳一跳功能,本文圖文并茂通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12C++?Cartographer源碼中關(guān)于MapBuilder的聲明與構(gòu)造
這篇文章主要介紹了C++?Cartographer源碼中關(guān)于MapBuilder的聲明與構(gòu)造,前面已經(jīng)談到了Cartographer中添加軌跡的方法和傳感器的數(shù)據(jù)流動(dòng)走向。在添加軌跡的時(shí)候,除了添加位姿估計(jì)器還有采樣器,訂閱回調(diào)函數(shù)之外,最重要的是通過map_builder_bridge添加了一條軌跡2023-03-03