C#實(shí)現(xiàn)TCP和UDP通信的示例詳解
C#在命名空間System.Net.Sockets
中對(duì)伯克利套接字提供了良好的封裝,提供了完善的TCP和UDP通信功能。
從編程的角度出發(fā),TCP和UDP最大的區(qū)別是,TCP存在TcpClient
和TcpLinster
兩個(gè)對(duì)象用于信息的傳遞,二者一發(fā)一收,十分完備。而UDP則只有一個(gè)類UdpClient
,換言之,UDP通信是不分服務(wù)端和客戶端,通信雙方對(duì)等。
UDP發(fā)送
至少在形式上,UDP比TCP更簡(jiǎn)單,所以先從UDP講起。
考慮到通信那肯定是有發(fā)有收才行,如果只用C#自己,那么肯定得上個(gè)多線程什么的才能跑通。為了避免問(wèn)題復(fù)雜化,故推薦使用這款NetAssist
網(wǎng)絡(luò)助手。
有了這個(gè),只要在C#里寫(xiě)一套發(fā)送代碼,就可以在NetAssist
上看到發(fā)送的內(nèi)容,比較實(shí)用。又因?yàn)椴捎庙敿?jí)語(yǔ)句,導(dǎo)致用下面這區(qū)區(qū)幾行代碼就可以完成一次套接字編程的實(shí)踐,非常劃算
using System.Net.Sockets; using System.Net; using System.Text; //由于收發(fā)都在本機(jī),所以只用一個(gè)IP地址 IPAddress addr = IPAddress.Parse("127.0.0.1"); var ptLocal = new IPEndPoint(addr, 9001); //本機(jī)節(jié)點(diǎn),用于發(fā)送 var ptDst = new IPEndPoint(addr, 9002); //目標(biāo)節(jié)點(diǎn) var udp = new UdpClient(ptLocal); //在本地建立udp服務(wù) byte[] buffer = Encoding.UTF8.GetBytes("hello"); udp.Send(buffer, buffer.Length, ptDst); //將內(nèi)容發(fā)給ptDst
效果為
在網(wǎng)絡(luò)中,兩個(gè)電腦要想通信,那么必須要知道彼此的位置,而在網(wǎng)絡(luò)中描述一個(gè)計(jì)算機(jī)的位置,用的就是IP地址。但光有一個(gè)地址還不行,計(jì)算機(jī)要處理這么多任務(wù),接收這么多服務(wù),在IP地址之外還得有個(gè)端口才可以。這種感覺(jué)大致相當(dāng)于,IP是一棟樓,端口就是門(mén)牌號(hào)。
而127.0.0.1是一個(gè)特殊的地址,即主機(jī)環(huán)回地址,很好理解,就是指向本地的地址,有了這個(gè),就可以自己和自己通信了。
UDP接收
發(fā)送和接收看上去是對(duì)偶,但難度上完全是兩回事,這種感覺(jué)就像你給女神發(fā)消息,其實(shí)很方便,按下發(fā)送鍵就完事兒了。但你等女神的消息,那就比較煎熬,因?yàn)槟悴淮_定她什么時(shí)候會(huì)發(fā)過(guò)來(lái),所以得一直等著。
所以,接收比發(fā)送麻煩多了,最起碼得有一個(gè)死循環(huán),如果對(duì)方?jīng)]消息,就死等。
// 前面的代碼和發(fā)送代碼一樣 while (true) { var received = udp.Receive(ref ptDst); string info = Encoding.UTF8.GetString(received); info =$" {ptDst.Address}:{ptDst.Port}:{info}"; Console.WriteLine(info); byte[] buf = Encoding.UTF8.GetBytes("What are our children's names"); udp.Send(buf, buf.Length, ptDst); //將內(nèi)容發(fā)給ptDst }
其中udp.Receive
就起到死等的作用,如果收不到,程序就不執(zhí)行,最后結(jié)果如下
TCP發(fā)送
UDP協(xié)議的好處是,UdpClient
包打天下,既可以發(fā)送也可以接收,而發(fā)送者和接收者的身份,需要通過(guò)端口號(hào)來(lái)區(qū)分。
TCP則不然,TCP本身分為服務(wù)端和客戶端,服務(wù)端在C#
中用TcpListener
類來(lái)實(shí)現(xiàn),觀其名而知其義,服務(wù)端的作用是監(jiān)聽(tīng),相應(yīng)地客戶端TcpClient
用于發(fā)送。其通信邏輯是,客戶端將發(fā)送工具和消息內(nèi)容一起發(fā)送給服務(wù)端,服務(wù)端再用客戶端自己的發(fā)送工具進(jìn)行回信。
NetAssist
同樣提供了TCP的發(fā)送和接收功能,為了讓C#代碼相對(duì)簡(jiǎn)單,這里先選擇服務(wù)端,即TCP Server
,端口選擇9002
,接下來(lái)仍用最短的代碼來(lái)演示一下C#的TCP發(fā)送功能,需要注意客戶端和服務(wù)端的端口需要統(tǒng)一一下。
// 引用的命名空間還是上面這些 TcpClient tcp = new TcpClient("127.0.0.1", 9002); NetworkStream n = tcp.GetStream(); var w = new BinaryWriter(n); byte[] buffer = Encoding.UTF8.GetBytes("hello"); w.Write(buffer, 0, buffer.Length); w.Flush();
效果如下
TCP接收
TCP的接收從邏輯上來(lái)說(shuō)要比UDP更高級(jí)一點(diǎn),畢竟TcpListener
又稱服務(wù)端,名義上來(lái)說(shuō)要服務(wù)于所有人。
TcpListener serv = new TcpListener(IPAddress.Any, 9002); serv.Start(); Byte[] bytes = new Byte[256]; int i; while (true) { var c = serv.AcceptTcpClient(); var n = c.GetStream(); while ((i = n.Read(bytes, 0, bytes.Length)) != 0) { var msg = Encoding.ASCII.GetString(bytes, 0, i); Console.WriteLine($"Received: {msg}"); msg += ", too"; var data = Encoding.ASCII.GetBytes(msg); n.Write(data, 0, data.Length); } }
上面代碼中,serv.AcceptTcpClient()
根據(jù)監(jiān)控到的信息,返回一個(gè)新的客戶端對(duì)象;c.GetStream()
返回一個(gè)網(wǎng)絡(luò)流對(duì)象,和其他Stream
一樣,通過(guò)Read
方法,可以將二進(jìn)制數(shù)據(jù)寫(xiě)入到字節(jié)數(shù)組中。
效果如下
到此這篇關(guān)于C#實(shí)現(xiàn)TCP和UDP通信的示例詳解的文章就介紹到這了,更多相關(guān)C# TCP UDP通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入分析C#中WinForm控件之Dock順序調(diào)整的詳解
本篇文章是對(duì)C#中WinForm控件之Dock順序調(diào)整進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C#中將xml文件反序列化為實(shí)例時(shí)采用基類還是派生類的知識(shí)點(diǎn)討論
在本篇文章里小編給大家整理的是關(guān)于C#中將xml文件反序列化為實(shí)例時(shí)采用基類還是派生類的知識(shí)點(diǎn)討論,有需要的朋友們學(xué)習(xí)下。2019-11-11C#調(diào)用百度API實(shí)現(xiàn)活體檢測(cè)的方法
這篇文章主要給大家介紹了關(guān)于C#調(diào)用百度API實(shí)現(xiàn)活體檢測(cè)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09通過(guò)容器擴(kuò)展屬性IExtenderProvider實(shí)現(xiàn)WinForm通用數(shù)據(jù)驗(yàn)證組件
這篇文章介紹了通過(guò)容器擴(kuò)展屬性IExtenderProvider實(shí)現(xiàn)WinForm通用數(shù)據(jù)驗(yàn)證組件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12