程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# Socket學習筆記二

C# Socket學習筆記二

編輯:C#入門知識

C# Socket學習筆記二


小記:昨天咱們已經了解了Socket的通信原理,可是點對點的一次通信並不是我們想要的,那麼今天那我們就繼續學習異步通信,簡單來說就是服務器端和客戶端可以進行多次 互發信息的通信而不用擔心通道會關閉。在介紹異步通信時,客戶端和服務器端的連接和上面介紹的同步通信建立連接的方式是一樣的,只是接收和發送數據的方式改變了!   1.什麼是異步通信? 異步:客戶端請求之後,不必等到服務器回應之後就可以發送下一條請求,並行運行。 2.同步與異步的區別? 同步:我叫你吃飯,你若暫時有事情我就一直在那等,不干別的事情,直到你忙完。 異步:我叫你吃飯,你若暫時有事情,我就先撤,干點別的,你忙完了再通過某種方式,如電話,通知我。   異步通信的好處我理解的就是可以多次使用一個Socket增加網絡的吞吐量,提高資源的利用率。           下面開始代碼分析,和上篇的沒多大差別,就是發送和接收數據的方式變了:   服務器端:TcpServer.cs   復制代碼   1 using System;   2 using System.Collections.Generic;   3 using System.Linq;   4 using System.Text;   5 using System.Threading.Tasks;   6 using System.Net;   7 using System.Net.Sockets;   8 using System.Threading;   9   10   11 namespace TcpServer  12 {  13     class Program  14     {  15         public static Socket serverSocket;  16         public static Thread thread;  17   18         static void Main(string[] args)  19         {  20             //確定端口號  21             int port = 6000;  22   23             //設定連接IP  24             string host = "127.0.0.1";  25   26             //將IP地址字符串轉化為IP地址實例  27             IPAddress ip = IPAddress.Parse(host);  28   29             //將網絡端點表示為 IP 地址和端口號  30             IPEndPoint ipe = new IPEndPoint(ip, port);  31   32             //建立Socket   33             //addressFamily 參數一指定 Socket 類使用的尋址方案  34             //socketType    參數二指定 Socket 類的類型  35             //protocolType  參數三指定 Socket 使用的協議。   36             Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  37   38   39             //socket與本地終結點建立關聯  40             socket.Bind(ipe);  41             string strSend = "HelloClient";  42             //開始監聽端口  43             socket.Listen(10);  44             Console.WriteLine("服務端已開啟,等待客戶端連接.....\t" + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString());  45   46             //為新建的連接建立新的Socket目的為客戶端將要建立連接  47             serverSocket = socket.Accept();  48             Console.WriteLine("連接已建立......\t\t" + DateTime.Now.ToString() + DateTime.Now.Millisecond.ToString());  49             Console.WriteLine("客戶端->服務端:\t" + serverSocket.RemoteEndPoint + "->" + serverSocket.LocalEndPoint);  50               51             //while (true)  52             {  53                 string recStr =string.Empty;  54                 //定義緩沖區用於接收客戶端的數據  55                 byte[] recbyte = new byte[1024];  56               57                 //開始接收數據  58                 ReceiveData();  59                   60                 //服務端給客戶端回送消息  61                 strSend = "HelloClient";  62   63                 //服務端發送數據  64                 //strSend = Console.ReadLine();  65                 Send(strSend);  66   67                 //開啟線程監視客戶端是否斷開  68                 thread = new Thread(ClientConnectOrNot);  69                 Thread.Sleep(0);  70                 thread.Start();  71             72   73                 //serverSocket.Close();  74                 Console.ReadLine();  75             }  76         }  77   78         /// <summary>  79         /// 監視客戶端是否斷開  80         /// </summary>  81         public static void ClientConnectOrNot()  82         {  83             //Console.WriteLine(serverSocket.Poll(-1, SelectMode.SelectRead));  84             if (serverSocket.Poll(-1, SelectMode.SelectRead) == true)//客戶端斷開  85             {  86                 Console.WriteLine(serverSocket.RemoteEndPoint + "斷開了連接");  87                 thread.Abort();  88   89             }  90             else  91             {  92                 Console.WriteLine(thread.ThreadState);  93             }  94         }  95         #region  96         /// <summary>  97         /// 異步連接  98         /// </summary>  99         /// <param name="ip"></param> 100         /// <param name="port"></param> 101         /// <param name="clientSocket"></param> 102         public static void Connect(IPAddress ip, int port) 103         { 104             serverSocket.BeginConnect(ip, port, new AsyncCallback(ConnectCallback), serverSocket); 105         } 106  107         private static void ConnectCallback(IAsyncResult ar) 108         { 109             try 110             { 111                 Socket handler = (Socket)ar.AsyncState; 112                 handler.EndConnect(ar); 113             } 114             catch (SocketException ex) 115             { 116                 throw ex; 117             } 118         } 119         /// <summary> 120         /// 發送數據 121         /// </summary> 122         /// <param name="data"></param> 123         public static void Send(string data) 124         { 125             //Send(System.Text.Encoding.UTF8.GetBytes(data)); 126             //解決中文亂碼 127             Send(UTF8Encoding.UTF8.GetBytes(data)); 128  129             //byte[] byteData = UTF8Encoding.UTF8.GetBytes(data); 130             //Send(Encoding.ASCII.GetBytes(data)); 131         } 132         /// <summary> 133         /// 發送數據 134         /// </summary> 135         /// <param name="byteData"></param> 136         private static void Send(byte[] byteData) 137         { 138             try 139             { 140                 int length = byteData.Length; 141                 //byte[] head = BitConverter.GetBytes(length);               //這個為什麼不對,我也不清楚 142                 byte[] head = Encoding.ASCII.GetBytes(length.ToString());    //將發送數據的字節長度寫到報頭中 143                 //head.Length = 4;                                           //開始我想指定頭部4個字節長度用來存放字節的總數便於拆包 144                 byte[] data = new byte[head.Length + byteData.Length];       //發送包的總大小 145                 for (int i = 0; i < 3; i++) 146                 { 147                     data[i] = 0; 148                 } 149                 Array.Copy(head, data, head.Length);                         //將head復制到data中 150                 Array.Copy(byteData, 0, data, head.Length, byteData.Length); //將byteData復制到data中 151                  152                 serverSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), serverSocket); 153             } 154             catch (SocketException ex) 155             { 156                 throw ex; 157             } 158         } 159  160         private static void SendCallback(IAsyncResult ar) 161         { 162             try 163             { 164                 Socket handler = (Socket)ar.AsyncState; 165                 handler.EndSend(ar); 166             } 167             catch (SocketException ex) 168             { 169                 throw ex; 170             } 171         } 172  173         /// <summary> 174         /// 接收數據8個字節 175         /// </summary> 176         static byte[] MsgBuffer = new byte[8]; 177  178         /// <summary> 179         /// 接收消息 180         /// </summary> 181         public static void ReceiveData() 182         { 183             serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 184         } 185  186         /// <summary> 187         /// 回調接收數據 188         /// </summary> 189         /// <param name="ar"></param> 190         private static void ReceiveCallback(IAsyncResult ar) 191         { 192             try 193             { 194                 int REnd = serverSocket.EndReceive(ar); 195                 if (REnd > 0) 196                 { 197                     byte[] data = new byte[REnd]; 198                     Array.Copy(MsgBuffer, 0, data, 0, REnd); 199                     int Msglen = data.Length; 200                     //在此次可以對data進行按需處理 201                     serverSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 202                     Console.WriteLine("來自到客戶端{0}字節:{1} \tTime:{2}",REnd ,UTF8Encoding .UTF8.GetString(data, 0, Msglen),DateTime.Now.ToString()+ DateTime.Now.Millisecond.ToString()); 203                 } 204                 else 205                 { 206                     dispose(); 207                 } 208             } 209             catch (SocketException ex) 210             { 211                 throw ex; 212             } 213         } 214  215         /// <summary> 216         /// 釋放連接 217         /// </summary> 218         private static void dispose() 219         { 220             try 221             { 222                 serverSocket.Shutdown(SocketShutdown.Both); 223                 serverSocket.Close(); 224             } 225             catch (Exception ex) 226             { 227                 throw ex; 228             } 229         } 230         #endregion 231     } 232 }   客戶端 TcpClient.cs 復制代碼   1 using System;   2 using System.Collections.Generic;   3 using System.Linq;   4 using System.Text;   5 using System.Threading.Tasks;   6 using System.Net;   7 using System.Net.Sockets;   8 using System.Threading;   9   10 namespace TcpClient  11 {  12     class Program  13     {  14         static int port = 6000;                          //監聽端口號  15         static string host = "127.0.0.1";                //連接服務端IP  16         static IPAddress ip = IPAddress.Parse(host);     //將IP地址轉換為IP實例  17         static IPEndPoint ipe = new IPEndPoint(ip, port);//將網絡端點表示為 IP 地址和端口號  18         static Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立客戶端Socket  19   20         static Thread thread_client;  21         static void Main(string[] args)  22         {  23             Connect(ip, port);//異步連接  24             string sendStr = "Nice to meet you,Server!";  25             thread_client = new Thread(ClientConnectOrNot);  26             Thread.Sleep(0);  27             thread_client.Start();  28             {  29                 Console.WriteLine("服務器->客戶端:" + clientSocket.RemoteEndPoint + "->" + clientSocket.LocalEndPoint);  30                 Send(sendStr);  //發送消息  31                 ReceiveData();  //接收消息  32                 sendStr = Console.ReadLine();  33             }  34              35         }  36         /// <summary>  37         /// 判斷服務端是否關閉  38         /// </summary>  39         public static void ClientConnectOrNot()  40         {  41             if (clientSocket.Poll(-1, SelectMode.SelectRead) == true) //檢測服務端是否關閉  42             {  43                 Console.WriteLine(clientSocket.RemoteEndPoint+"服務端已關閉...");  44   45                 //thread_client.Abort();  46                 //Thread exit = new Thread(ApplicationExit); //自動關閉程序  47                 //Thread.Sleep(3000);  48                 //exit.Start();  49                   50             }  51             else  52             {  53                 Console.WriteLine(thread_client.ThreadState);  54             }  55         }  56         /// <summary>  57         /// 退出程序關閉Dos窗口  58         /// </summary>  59         public static void ApplicationExit()  60         {  61             Environment.Exit(0);  62         }  63   64         #region  65         /// <summary>  66         /// 異步連接  67         /// </summary>  68         /// <param name="ip"></param>  69         /// <param name="port"></param>  70         /// <param name="clientSocket"></param>  71         public static void Connect(IPAddress ip, int port)  72         {  73             clientSocket.BeginConnect(ip, port, new AsyncCallback(ConnectCallback), clientSocket);  74         }  75   76         private static void ConnectCallback(IAsyncResult ar)  77         {  78             try  79             {  80                 Socket handler = (Socket)ar.AsyncState;  81                 handler.EndConnect(ar);  82             }  83             catch (SocketException ex)  84             {  85                 throw ex;  86             }  87         }  88         /// <summary>  89         /// 發送數據  90         /// </summary>  91         /// <param name="data"></param>  92         public static void Send(string data)  93         {  94             //Send(System.Text.Encoding.UTF8.GetBytes(data));  95             //Send(Encoding.ASCII.GetBytes(data));  96             Send(UTF8Encoding.UTF8.GetBytes(data));  97         }  98         /// <summary>  99         /// 發送數據 100         /// </summary> 101         /// <param name="byteData"></param> 102         private static void Send(byte[] byteData) 103         { 104             try 105             { 106                 int length = byteData.Length; 107                 //byte[] head = BitConverter.GetBytes(length); 108                 byte[] head = Encoding.ASCII.GetBytes(length.ToString()); //頭部表示字節的總長度 109                 byte[] data = new byte[head.Length + byteData.Length]; 110                 Array.Copy(head, data, head.Length); 111                 Array.Copy(byteData, 0, data, head.Length, byteData.Length); 112                 clientSocket.BeginSend(data, 0, data.Length, 0, new AsyncCallback(SendCallback), clientSocket); 113             } 114             catch (SocketException ex) 115             { } 116         } 117         /// <summary> 118         /// 回調發送 119         /// </summary> 120         /// <param name="ar"></param> 121         private static void SendCallback(IAsyncResult ar) 122         { 123             try 124             { 125                 Socket handler = (Socket)ar.AsyncState; 126                 handler.EndSend(ar); 127             } 128             catch (SocketException ex) 129             { 130                 throw ex; 131             } 132         } 133  134         /// <summary> 135         /// 定義緩沖區接收數據8個字節 136         /// </summary> 137         static byte[] MsgBuffer = new byte[8]; 138  139         /// <summary> 140         /// 接收消息 141         /// </summary> 142         public static void ReceiveData() 143         { 144             clientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 145         } 146         static bool first = true; 147         private static void ReceiveCallback(IAsyncResult ar) 148         { 149             try 150             { 151                 int REnd = clientSocket.EndReceive(ar); 152                 if (REnd > 0) 153                 { 154                     byte[] data = new byte[REnd]; 155                     Array.Copy(MsgBuffer, 0, data, 0, REnd); 156  157                     int Msglen = data.Length; 158                     //在此次可以對data進行按需處理 159                      160                     clientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null); 161                     string revStr = UTF8Encoding .UTF8.GetString(data, 0, Msglen); 162                     if (first) 163                     { 164                         string len = revStr.Substring(0, 2); 165                         first = false; 166                     } 167                     Console.WriteLine("來自服務端{0}字節:{1}\tTime:{2}",REnd,revStr,DateTime.Now.ToString()+ DateTime.Now.Millisecond.ToString()); 168                 } 169                 else 170                 { 171                     dispose(); 172                 } 173             } 174             catch (SocketException ex) 175             { } 176         } 177         /// <summary> 178         /// 釋放Socket 179         /// </summary> 180         private static void dispose() 181         { 182             try 183             { 184                 clientSocket.Shutdown(SocketShutdown.Both); 185                 clientSocket.Close(); 186             } 187             catch (Exception ex) 188             { 189                 throw ex; 190             } 191         } 192         #endregion 193     } 194 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved