C#之Socket(套接字)通信
一、socket是什么
Socket是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。在設(shè)計(jì)模式中,Socket其實(shí)就是一個(gè)門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。所以,我們無需深入理解tcp/udp協(xié)議,socket已經(jīng)為我們封裝好了,我們只需要遵循socket的規(guī)定去編程,寫出的程序自然就是遵循tcp/udp標(biāo)準(zhǔn)的。
二、套接字的工作流程
先從服務(wù)器端說起。服務(wù)器端先初始化Socket,然后與端口綁定(bind),對端口進(jìn)行監(jiān)聽(listen),調(diào)用accept阻塞,等待客戶端連接。在這時(shí)如果有個(gè)客戶端初始化一個(gè)Socket,然后連接服務(wù)器(connect),如果連接成功,這時(shí)客戶端與服務(wù)器端的連接就建立了。客戶端發(fā)送數(shù)據(jù)請求,服務(wù)器端接收請求并處理請求,然后把回應(yīng)數(shù)據(jù)發(fā)送給客戶端,客戶端讀取數(shù)據(jù),最后關(guān)閉連接,一次交互結(jié)束。
三、服務(wù)端
private void btnListen_Click(object sender, EventArgs e) { IPEndPoint point = new IPEndPoint(IPAddress.Any, 13000);//IPAddress.Any本機(jī)任何網(wǎng)卡IP。本機(jī)端口查看netstat -an //服務(wù)端Socket定義 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Bind(point); //綁定IP socket.Listen(10);//啟動(dòng)監(jiān)聽。最大監(jiān)聽數(shù),同一個(gè)時(shí)間點(diǎn)過來10個(gè)客戶端,排隊(duì) ShowMsg("服務(wù)器開始監(jiān)聽"); Thread thread = new Thread(AcceptInfo); thread.Start(socket); } //記錄通信用的Socket Dictionary<string, Socket> dic = new Dictionary<string, Socket>(); // private Socket client; void AcceptInfo(object o) { Socket socket = o as Socket; while (true) { //通信用socket try { Socket clientSocket = socket.Accept();//如果客戶端有請求,生成一個(gè)新的Socket string point = clientSocket.RemoteEndPoint.ToString(); ShowMsg(point + "連接客戶端成功!"); dic.Add(point, clientSocket); //接收消息 Thread th = new Thread(ReceiveMsg); th.Start(clientSocket); } catch (Exception ex) { break; } } socket.Close(); } //接收消息 void ReceiveMsg(object socket) { Socket clientSocket = socket as Socket; while (true) { //接收客戶端發(fā)送過來的數(shù)據(jù) try { //定義byte數(shù)組存放從客戶端接收過來的數(shù)據(jù) byte[] buffer = new byte[1024 * 1024]; int n = clientSocket.Receive(buffer);//將接收過來的數(shù)據(jù)放到buffer中,并返回實(shí)際接受數(shù)據(jù)的長度 //將字節(jié)轉(zhuǎn)換成字符串 string words = Encoding.Unicode.GetString(buffer, 0, n); Console.WriteLine(clientSocket.RemoteEndPoint.ToString() + ":" + words); byte[] msg = Encoding.Unicode.GetBytes(words); clientSocket.Send(msg);//發(fā)送數(shù)據(jù),字節(jié)數(shù)組 } catch (Exception ex) { break; } } clientSocket.Shutdown(SocketShutdown.Both);//禁止發(fā)送和接受數(shù)據(jù) clientSocket.Close();//關(guān)閉socket,釋放資源 }
四、客戶端
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint point = new IPEndPoint("127.0.0.1", 13000));//連接到的服務(wù)端IP clientSocket.Connect(point);//連接到服務(wù)器 ShowMsg("連接成功"); ShowMsg("服務(wù)器" + client.RemoteEndPoint.ToString()); ShowMsg("客戶端:" + client.LocalEndPoint.ToString()); Thread th = new Thread(ReceiveMsg);//連接成功后,就可以接收服務(wù)器發(fā)送的信息了 th.IsBackground = true; th.Start(); clientSocket.Shutdown(SocketShutdown.Both);//禁止發(fā)送和接受數(shù)據(jù) clientSocket.Close();//關(guān)閉socket,釋放資源
五、Socket對象的成員
1、屬性
名稱 | 說明 |
---|---|
AddressFamily | 獲取 Socket 的地址族。 |
Available | 獲取已經(jīng)從網(wǎng)絡(luò)接收且可供讀取的數(shù)據(jù)量。 |
Blocking | 獲取或設(shè)置一個(gè)值,該值指示 Socket 是否處于阻止模式。 |
Connected | 獲取一個(gè)值,該值指示 Socket 是在上次 Send 還是 Receive 操作時(shí)連接到遠(yuǎn)程主機(jī)。 |
Handle | 獲取 Socket 的操作系統(tǒng)句柄。 |
LocalEndPoint | 獲取本地終結(jié)點(diǎn)。 |
RemoteEndPoint | 獲取遠(yuǎn)程終結(jié)點(diǎn)。 |
ProtocolType | 獲取 Socket 的協(xié)議類型。 |
SocketType | 獲取 Socket 的類型。 |
ReceiveBufferSize | 獲取或設(shè)置一個(gè)值,它指定 Socket 接收緩沖區(qū)的大小。 |
ReceiveTimeout | 獲取或設(shè)置一個(gè)值,該值指定之后同步 Receive 調(diào)用將超時(shí)的時(shí)間長度。 |
SendBufferSize | 獲取或設(shè)置一個(gè)值,該值指定 Socket 發(fā)送緩沖區(qū)的大小。 |
SendTimeout | 獲取或設(shè)置一個(gè)值,該值指定之后同步 Send 調(diào)用將超時(shí)的時(shí)間長度。 |
2、方法
Accept
名稱 | 說明 |
---|---|
Accept() | 為新建連接創(chuàng)建新的 Socket。 |
BeginAccept(AsyncCallback, Object) | 開始一個(gè)異步操作來接受一個(gè)傳入的連接嘗試。 |
EndAccept(Byte[], IAsyncResult) | 異步接受傳入的連接嘗試,并創(chuàng)建新的 Socket 對象來處理遠(yuǎn)程主機(jī)通信。 此方法返回包含所傳輸?shù)某跏紨?shù)據(jù)的緩沖區(qū)。 |
AcceptAsync(SocketAsyncEventArgs) | 開始一個(gè)異步操作來接受一個(gè)傳入的連接嘗試。 |
Connect
名稱 | 說明 |
---|---|
Connect(EndPoint) | 與遠(yuǎn)程主機(jī)建立連接。 |
BeginConnect(EndPoint, AsyncCallback, Object) | 開始一個(gè)對遠(yuǎn)程主機(jī)連接的異步請求。 |
EndConnect(IAsyncResult) | 結(jié)束掛起的異步連接請求。 |
ConnectAsync(SocketAsyncEventArgs) | 開始一個(gè)對遠(yuǎn)程主機(jī)連接的異步請求。 |
Disconnect
名稱 | 說明 |
---|---|
Disconnect(Boolean) | 關(guān)閉套接字連接并允許重用套接字。 |
BeginDisconnect(Boolean, AsyncCallback, Object) | 開始異步請求從遠(yuǎn)程終結(jié)點(diǎn)斷開連接。 |
EndDisconnect(IAsyncResult) | 結(jié)束掛起的異步斷開連接請求。 |
DisconnectAsync(SocketAsyncEventArgs) | 關(guān)閉套接字連接并允許重用套接字。 |
Receive
名稱 | 說明 |
---|---|
Receive(Byte[]) | 從綁定的 Socket 套接字接收數(shù)據(jù),將數(shù)據(jù)存入接收緩沖區(qū)。 |
BeginReceive(Byte[], Int32, Int32, SocketFlags, AsyncCallback, Object) | 開始從連接的 Socket 中異步接收數(shù)據(jù)。 |
EndReceive(IAsyncResult) | 結(jié)束掛起的異步讀取。 |
ReceiveAsync(SocketAsyncEventArgs) | 開始一個(gè)異步請求以便從連接的 Socket 對象中接收數(shù)據(jù)。 |
ReceiveFrom
名稱 | 說明 |
---|---|
ReceiveFrom(Byte[], EndPoint) | 將數(shù)據(jù)報(bào)接收到數(shù)據(jù)緩沖區(qū)并存儲(chǔ)終結(jié)點(diǎn)。 |
BeginReceiveFrom(Byte[], Int32, Int32, SocketFlags, EndPoint, AsyncCallback, Object) | 開始從指定網(wǎng)絡(luò)設(shè)備中異步接收數(shù)據(jù)。 |
EndReceiveFrom(IAsyncResult, EndPoint) | 結(jié)束掛起的、從特定終結(jié)點(diǎn)進(jìn)行異步讀取。 |
ReceiveFromAsync(SocketAsyncEventArgs) | 開始從指定網(wǎng)絡(luò)設(shè)備中異步接收數(shù)據(jù)。 |
ReceiveMessageFrom
名稱 | 說明 |
---|---|
ReceiveMessageFrom(Byte[], Int32, Int32, SocketFlags, EndPoint, IPPacketInformation) | 使用指定的 SocketFlags 將指定字節(jié)數(shù)的數(shù)據(jù)接收到指定的數(shù)據(jù)緩沖區(qū)位置,并存儲(chǔ)終結(jié)點(diǎn)和數(shù)據(jù)包信息。 |
BeginReceiveMessageFrom(Byte[], Int32, Int32, SocketFlags, EndPoint, AsyncCallback, Object) | 開始使用指定的 SocketFlags 將指定字節(jié)數(shù)的數(shù)據(jù)異步接收到數(shù)據(jù)緩沖區(qū)的指定位置,然后存儲(chǔ)終結(jié)點(diǎn)和數(shù)據(jù)包信息。 |
EndReceiveMessageFrom(IAsyncResult, SocketFlags, EndPoint, IPPacketInformation) | 結(jié)束掛起的、從特定終結(jié)點(diǎn)進(jìn)行異步讀取。 此方法還顯示有關(guān)數(shù)據(jù)包而不是 EndReceiveFrom(IAsyncResult, EndPoint) 的更多信息。 |
ReceiveMessageFromAsync(SocketAsyncEventArgs) | 開始使用指定的 SocketFlags 將指定字節(jié)數(shù)的數(shù)據(jù)異步接收到數(shù)據(jù)緩沖區(qū)的指定位置,并存儲(chǔ)終結(jié)點(diǎn)和數(shù)據(jù)包信息。 |
Send
名稱 | 說明 |
---|---|
Send(Byte[]) | 將數(shù)據(jù)發(fā)送到連接的 Socket。 |
BeginSend(Byte[], Int32, Int32, SocketFlags, AsyncCallback, Object) | 將數(shù)據(jù)異步發(fā)送到連接的 Socket。 |
EndSend(IAsyncResult) | 結(jié)束掛起的異步發(fā)送。 |
SendAsync(SocketAsyncEventArgs) | 將數(shù)據(jù)異步發(fā)送到連接的 Socket 對象。 |
SendFile
名稱 | 說明 |
---|---|
SendFile(String) | 使用 Socket 傳輸標(biāo)志,將文件 fileName 發(fā)送到連接的 UseDefaultWorkerThread 對象。 |
BeginSendFile(String, AsyncCallback, Object) | 使用 Socket 標(biāo)志,將文件 fileName 發(fā)送到連接的 UseDefaultWorkerThread 對象。 |
EndSendFile(IAsyncResult) | 結(jié)束文件的掛起異步發(fā)送。 |
SendTo
名稱 | 說明 |
---|---|
SendTo(Byte[], EndPoint) | 將數(shù)據(jù)發(fā)送到指定的終結(jié)點(diǎn)。 |
BeginSendTo(Byte[], Int32, Int32, SocketFlags, EndPoint, AsyncCallback, Object) | 以異步方式將數(shù)據(jù)發(fā)送到特定遠(yuǎn)程主機(jī)。 |
EndSendTo(IAsyncResult) | 結(jié)束掛起的、向指定位置進(jìn)行的異步發(fā)送。 |
SendToAsync(SocketAsyncEventArgs) | 以異步方式將數(shù)據(jù)發(fā)送到特定遠(yuǎn)程主機(jī)。 |
其它
名稱 | 說明 |
---|---|
Select(IList, IList, IList, Int32) | 確定一個(gè)或多個(gè)套接字的狀態(tài)。 |
SendPacketsAsync(SocketAsyncEventArgs) | 將文件集合或者內(nèi)存中的數(shù)據(jù)緩沖區(qū)以異步方法發(fā)送給連接的 Socket 對象。 |
Bind(EndPoint) | 使 Socket 與一個(gè)本地終結(jié)點(diǎn)相關(guān)聯(lián)。 |
Listen(Int32) | 將 Socket 置于偵聽狀態(tài)。 |
CancelConnectAsync(SocketAsyncEventArgs) | 取消一個(gè)對遠(yuǎn)程主機(jī)連接的異步請求。 |
GetSocketOption(SocketOptionLevel, SocketOptionName) | 返回指定的 Socket 選項(xiàng)的值,表示為一個(gè)對象。 |
SetSocketOption(SocketOptionLevel, SocketOptionName, Boolean) | 將指定的 Socket 選項(xiàng)設(shè)置為指定的 Boolean 值。 |
SetIPProtectionLevel(IPProtectionLevel) | 設(shè)置套接字的 IP 保護(hù)級(jí)別。 |
Shutdown(SocketShutdown) | 禁用某 Socket 上的發(fā)送和接收。 |
Close() | 關(guān)閉 Socket 連接并釋放所有關(guān)聯(lián)的資源。 |
Dispose() | 釋放 Socket 類的當(dāng)前實(shí)例所使用的所有資源。 |
到此這篇關(guān)于C#之Socket(套接字)通信的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#調(diào)用barTender打印標(biāo)簽示例的實(shí)現(xiàn)
Bartender是最優(yōu)秀的條碼打印軟件,在企業(yè)里使用非常普遍,本文主要介紹了C#調(diào)用barTender打印標(biāo)簽示例的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08C#實(shí)現(xiàn)通過winmm.dll控制聲音播放的方法
這篇文章主要介紹了C#實(shí)現(xiàn)通過winmm.dll控制聲音播放的方法,很實(shí)用的功能,需要的朋友可以參考下2014-08-08Unity實(shí)現(xiàn)手機(jī)搖一搖震動(dòng)
這篇文章主要為大家詳細(xì)介紹了untiy實(shí)現(xiàn)手機(jī)搖一搖震動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11C#中string和StingBuilder內(nèi)存中的區(qū)別實(shí)例分析
這篇文章主要介紹了C#中string和StingBuilder內(nèi)存中的區(qū)別,以實(shí)例形式演示了二者在內(nèi)存中的不同之處,需要的朋友可以參考下2014-09-09詳解C# WebApi 接口測試工具:WebApiTestClient
這篇文章主要介紹了詳解C# WebApi 接口測試工具:WebApiTestClient,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07C#實(shí)現(xiàn)獲取計(jì)算機(jī)信息的示例代碼
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)獲取計(jì)算機(jī)軟硬件信息的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2024-01-01