dotnet socket
阿新 • • 發佈:2020-07-01
服務端操作
//1、建立IPE int port = 6000; string host = "127.0.0.1"; IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEndPoint(ip, port); //2、建立socket Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //3、繫結埠與ip //如果要指定本地 IP 地址和埠號,請在呼叫 Listen 方法之前呼叫 Bind 方法 sSocket.Bind(ipe); //4、監聽,如果希望基礎服務提供商為你分配一個可用埠,請使用埠號零 //如果使用面向連線的協議(例如 TCP),則伺服器可以使用 Listen 方法偵聽連線 sSocket.Listen(0); Console.WriteLine("監聽已經開啟,請等待"); //5、獲取通訊socket //receive message, Accept 方法處理任何傳入連線請求,並返回可用於與遠端主機通訊的 Socket Socket serverSocket = sSocket.Accept(); Console.WriteLine("連線已經建立"); string recStr = ""; byte[] recByte = new byte[4096]; //6、接收資料。若要傳遞資料,請呼叫 Send 或 Receive 方法 int bytes = serverSocket.Receive(recByte, recByte.Length, 0); recStr += Encoding.ASCII.GetString(recByte, 0, bytes); //send message Console.WriteLine("伺服器端獲得資訊:{0}", recStr); string sendStr = "send to client :hello"; byte[] sendByte = Encoding.ASCII.GetBytes(sendStr); //7、傳送資料 serverSocket.Send(sendByte, sendByte.Length, 0); serverSocket.Close(); sSocket.Close();
client
//1、建立ipe int port = 6000; string host = "127.0.0.1";//伺服器端ip地址 IPAddress ip = IPAddress.Parse(host); IPEndPoint ipe = new IPEndPoint(ip, port); //2、建立socket Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //3、connect clientSocket.Connect(ipe); //4、send message string sendStr = "send to server : hello,ni hao"; byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr); clientSocket.Send(sendBytes); //5、receive message string recStr = ""; byte[] recBytes = new byte[4096]; int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0); recStr += Encoding.ASCII.GetString(recBytes, 0, bytes); Console.WriteLine(recStr); clientSocket.Close();
下面的程式碼實現非同步:
using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; // 客戶端請求狀態資訊儲存在這裡 public class StateObject { // Client socket. // 客戶端的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(); } public class AsynchronousSocketListener { public static List<Socket> ClientSockets = new List<Socket>(); // 執行緒訊號 public static ManualResetEvent allDone = new ManualResetEvent(false); /// <summary> /// 建構函式 /// </summary> public AsynchronousSocketListener() { } /// <summary> /// 開始監聽 /// </summary> public static void StartListening() { // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[3]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(100); Task.Run(()=> { while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. // AsyncCallback 讓回撥函式在單獨的執行緒中執行 Console.WriteLine("Waiting for a connection..."); // 處理傳入的請求 listener.BeginAccept( new AsyncCallback(AcceptCallback), listener); // Wait until a connection is made before continuing. allDone.WaitOne(); } }); while (true) { for (int i = 0; i < ClientSockets.Count; i++) { try { Send(ClientSockets[i], "hello i am server\r\n"); } catch (Exception) { ClientSockets.RemoveAt(i); } } Thread.Sleep(100); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } /// <summary> /// 監聽回撥 /// </summary> /// <param name="ar"></param> public static void AcceptCallback(IAsyncResult ar) { // 標記主執行緒繼續執行 allDone.Set(); // 獲取socket來處理client請求 Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // 建立資料物件(儲存接收資料) StateObject state = new StateObject(); state.workSocket = handler; ClientSockets.Add(handler); Console.WriteLine(ClientSockets.Count); // 處理傳遞進來的資料 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } /// <summary> /// 讀取客戶端請求資料回撥 /// </summary> /// <param name="ar"></param> public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. // 在read回撥函式中呼叫 IAsyncResult(ar) 的 AsyncState 方法,以獲取傳遞給 BeginReceive 方法的狀態物件 // 此時就已經獲取到客戶端請求的資料,儲存在state.buffer中,如果此時還有資料進來也不會填充state的buffer,而是等待下一次回撥被呼叫 StateObject state = (StateObject)ar.AsyncState; // 從此狀態物件中提取接收 Socket Socket handler = state.workSocket; // Read data from the client socket. // 獲取 Client Socket後,可以呼叫 EndReceive 方法成功完成(關閉) BeginReceive 方法中啟動的非同步讀取操作,並返回所讀取的位元組數 int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. // 可能會有很多資料要接收,暫存當前已經接收到的資料,StateObject.buffer在ar.AsyncState的時候就已經被填充(實測) state.sb.Clear(); state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. // 檢查end-of-file,如果沒喲檢測到就再繼續讀。 content = state.sb.ToString(); Console.WriteLine(content); /* if (content.IndexOf("<EOF>") > -1) { // All the data has been read from the // client. Display it on the console. Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content); // Echo the data back to the client. Send(handler, content); } else { // Not all data received. Get more. // 沒有讀取到所有資料,繼續讀取,這裡是個遞迴 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); }*/ handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } private static void Send(Socket handler, String data) { // Convert the string data to byte data using ASCII encoding. // 轉換string到位元組陣列。使用ASCII編碼 byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. // 開始傳送,非同步傳送 // 這裡的handler是客戶端client請求來的 handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } /// <summary> /// 傳送回撥,傳送什麼如何傳送在這裡實現 /// </summary> /// <param name="ar"></param> private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object // 獲取socket ,ar.AsyncState返回的是個object型別,可以轉為state也可以轉為socket Socket handler = (Socket)ar.AsyncState; // Complete sending the data to the remote device. // 在回撥方法中,呼叫 IAsyncResult 引數的 AsyncState 方法以獲取傳送 Socket。 // 獲取 Socket後,可以呼叫 EndSend 方法成功完成傳送操作,並返回傳送的位元組數。 int bytesSent = handler.EndSend(ar); //Console.WriteLine("Sent {0} 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 0; } }