詳解C# Socket異步通信實(shí)例
TCPServer
1、使用的通訊通道:socket
2、用到的基本功能:
①Bind,
②Listen,
③BeginAccept
④EndAccept
⑤BeginReceive
⑥EndReceive
3、函數(shù)參數(shù)說(shuō)明
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
新建socket所使用的參數(shù)均為系統(tǒng)預(yù)定義的量,直接選取使用。
listener.Bind(localEndPoint);
localEndPoint 表示一個(gè)定義完整的終端,包括IP和端口信息。
//new IPEndPoint(IPAddress,port) //IPAdress.Parse("192.168.1.3") listener.Listen(100);
監(jiān)聽(tīng)
listener.BeginAccept( new AsyncCallback(AcceptCallback), listener);
AsyncCallback(AcceptCallback),一旦連接上后的回調(diào)函數(shù)為AcceptCallback。當(dāng)系統(tǒng)調(diào)用這個(gè)函數(shù)時(shí),自動(dòng)賦予的輸入?yún)?shù)為IAsyncResoult類(lèi)型變量ar。
listener,連接行為的容器。
Socket handler = listener.EndAccept(ar);
完成連接,返回此時(shí)的socket通道。
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
接收的字節(jié),0,字節(jié)長(zhǎng)度,0,接收時(shí)調(diào)用的回調(diào)函數(shù),接收行為的容器。
========
容器的結(jié)構(gòu)類(lèi)型為:
public class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = 1024; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); }
容器至少為一個(gè)socket類(lèi)型。
===============
// Read data from the client socket. int bytesRead = handler.EndReceive(ar);
完成一次連接。數(shù)據(jù)存儲(chǔ)在state.buffer里,bytesRead為讀取的長(zhǎng)度。
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
發(fā)送數(shù)據(jù)byteData,回調(diào)函數(shù)SendCallback。容器handler
int bytesSent = handler.EndSend(ar);
發(fā)送完畢,bytesSent發(fā)送字節(jié)數(shù)。
4 程序結(jié)構(gòu)
主程序:
byte[] bytes = new Byte[1024]; IPAddress ipAddress = IPAddress.Parse("192.168.1.104"); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // 生成一個(gè)TCP的socket Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Set the event to nonsignaled state. allDone.Reset(); //開(kāi)啟異步監(jiān)聽(tīng)socket Console.WriteLine("Waiting for a connection"); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // 讓程序等待,直到連接任務(wù)完成。在AcceptCallback里的適當(dāng)位置放置allDone.Set()語(yǔ)句. allDone.WaitOne(); } Console.WriteLine("\nPress ENTER to continue"); Console.Read();
連接行為回調(diào)函數(shù)AcceptCallback:
public static void AcceptCallback(IAsyncResult ar) { //添加此命令,讓主線程繼續(xù). allDone.Set(); // 獲取客戶(hù)請(qǐng)求的socket Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // 造一個(gè)容器,并用于接收命令. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); }
讀取行為的回調(diào)函數(shù)ReadCallback:
public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; // 從異步state對(duì)象中獲取state和socket對(duì)象. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; // 從客戶(hù)socket讀取數(shù)據(jù). int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // 如果接收到數(shù)據(jù),則存起來(lái) state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); // 檢查是否有結(jié)束標(biāo)記,如果沒(méi)有則繼續(xù)讀取 content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { //所有數(shù)據(jù)讀取完畢. Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content); // 給客戶(hù)端響應(yīng). Send(handler, content); } else { // 接收未完成,繼續(xù)接收. handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } }
發(fā)送消息給客戶(hù)端:
private static void Send(Socket handler, String data) { // 消息格式轉(zhuǎn)換. byte[] byteData = Encoding.ASCII.GetBytes(data); // 開(kāi)始發(fā)送數(shù)據(jù)給遠(yuǎn)程目標(biāo). handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { // 從state對(duì)象獲取socket. Socket handler = (Socket)ar.AsyncState; //完成數(shù)據(jù)發(fā)送 int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both); handler.Close(); }
在各種行為的回調(diào)函數(shù)中,所對(duì)應(yīng)的socket都從輸入?yún)?shù)的AsyncState屬性獲得。使用(Socket)或者(StateObject)進(jìn)行強(qiáng)制轉(zhuǎn)換。BeginReceive函數(shù)使用的容器為state,因?yàn)樗枰娣艂魉偷臄?shù)據(jù)。
而其余接收或發(fā)送函數(shù)的容器為socket也可。
完整代碼
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; // State object for reading client data asynchronously public class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = ; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); } public class AsynchronousSocketListener { // Thread signal. public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() { } public static void StartListening() { // Data buffer for incoming data. byte[] bytes = new Byte[]; // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = IPAddress.Parse("..."); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, ); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(); while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. Console.WriteLine("Waiting for a connection"); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing. allDone.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue"); Console.Read(); } public static void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive(state.buffer, , StateObject.BufferSize, , new AsyncCallback(ReadCallback), state); } public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; // Read data from the client socket. int bytesRead = handler.EndReceive(ar); if (bytesRead > ) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.ASCII.GetString( state.buffer, , bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -) { // All the data has been read from the // client. Display it on the console. Console.WriteLine("Read {} bytes from socket. \n Data : {}",content.Length, content); // Echo the data back to the client. Send(handler, content); } else { // Not all data received. Get more. handler.BeginReceive(state.buffer, , StateObject.BufferSize, , new AsyncCallback(ReadCallback), state); } } } private static void Send(Socket handler, String data) { // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. handler.BeginSend(byteData, , byteData.Length, , new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both); handler.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { StartListening(); return ; } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Unity游戲開(kāi)發(fā)中必備的設(shè)計(jì)模式之外觀模式詳解
外觀模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,為復(fù)雜系統(tǒng)提供了簡(jiǎn)單的接口,使得子系統(tǒng)間的通信更加簡(jiǎn)潔和易于維護(hù)。在Unity游戲開(kāi)發(fā)中,外觀模式可以幫助開(kāi)發(fā)者更好地管理游戲?qū)ο蠛徒M件等復(fù)雜結(jié)構(gòu)2023-05-05利用C#/VB.NET實(shí)現(xiàn)將PDF轉(zhuǎn)為Word
眾所周知,PDF 文檔支持特長(zhǎng)文件,集成度和安全可靠性都較高,可有效防止他人對(duì) PDF 內(nèi)容進(jìn)行更改,所以在工作中深受大家喜愛(ài)。本文將分為兩部分介紹如何以編程的方式將 PDF 轉(zhuǎn)換為 Word,需要的可以參考一下2022-12-12C#實(shí)現(xiàn)DataTable轉(zhuǎn)換成IList的方法
這篇文章主要介紹了C#實(shí)現(xiàn)DataTable轉(zhuǎn)換成IList的方法,涉及C#針對(duì)DataTable操作的相關(guān)技巧,需要的朋友可以參考下2016-03-03C#使用HtmlAgilityPack實(shí)現(xiàn)解析提取HTML內(nèi)容
HtmlAgilityPack是一個(gè)HTML解析類(lèi)庫(kù),這篇文章主要為大家詳細(xì)介紹了C#如何使用HtmlAgilityPack實(shí)現(xiàn)解析提取HTML內(nèi)容,感興趣的小伙伴可以參考一下2023-12-12C#實(shí)現(xiàn)幾十萬(wàn)級(jí)數(shù)據(jù)導(dǎo)出Excel及Excel各種操作實(shí)例
本篇文章主要介紹了C#實(shí)現(xiàn)幾十萬(wàn)級(jí)數(shù)據(jù)導(dǎo)出Excel及Excel各種操作實(shí)例,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-02-02C#中靜態(tài)構(gòu)造函數(shù)的幾點(diǎn)說(shuō)明介紹
本篇文章主要是對(duì)C#中靜態(tài)構(gòu)造函數(shù)的幾點(diǎn)說(shuō)明進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼
這篇文章主要介紹了使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07