接下來是服務器部分,采用異步模式,新建了一個AsynServer類,用於存放socket服務器代碼,主要有4個方法:
有一個全局socket,下面四個方法中都用到。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
類框架如下:
1.構造方法public AsynServer(IPEndPoint endpoint,int listenMaxNum)
用於初始化socket服務器,IPEndPoint參數是socket綁定的終結點,listenMaxNum參數是監聽隊列的掛起的最大長度,代碼如下:
public AsynServer(IPEndPoint endpoint,int listenMaxNum) { socket.Bind(endpoint); //綁定終結點 socket.Listen(listenMaxNum);//將socket至於偵聽狀態,設置掛起隊列最大值為listenMaxNum Console.WriteLine("正在連接客戶端...."); AsynAccept(); //開始異步監聽 // return socket; }
2.異步監聽方法public void AsynAccept()
public void AsynAccept() { socket.BeginAccept(asyncResult => { socket = socket.EndAccept(asyncResult); //異步監聽成功,返回socket Console.WriteLine("客戶端{0}異步連接成功", socket.RemoteEndPoint.ToString()); AsynReceive(); AsynSend("Server:Hello,client!"); }, null); } View Code需注意的是異步socket的BeginAccept()方法必須以EndAccept()方法結束,EndAccept(asyncResult)通過回調BeginAccept中的asyncResult狀態信息返回socket,這個socket是與客戶端建立連接後的socket,需要把它賦給全局socket(後面的方法中會調用)。
另外,AsynAccept並不會阻塞主線程,因為系統會為BeginAccept()方法自動開一個線程,並阻塞該線程直到收到客戶端連接,回調lamda表達式中的接收代碼。
采用lamda變得式寫的回調函數,不熟悉的同學請惡補一下吧,用起來很方便的:-)
連接成功了會收到客戶端發來的信息,(AsynReceive()也是異步的,不會阻礙主線程),並給客戶端發送問候信息,(AsynReceive()和AsynSend()都是異步的,不會阻礙主線程)。
3.異步接收方法private void AsynReceive()
private void AsynReceive() { byte[] data = new byte[1024];//接收緩存 string receiveStr; socket.BeginReceive(data, 0, data.Length, SocketFlags.None, asyncResult => { int length = socket.EndReceive(asyncResult); if (length != 0) { receiveStr = Encoding.ASCII.GetString(data, 0, length);//獲取緩存中的信息 Console.WriteLine(receiveStr); AsynReceive();//繼續開新線程接收 } else { Console.WriteLine("客戶端{0}:關閉socket連接", socket.RemoteEndPoint.ToString());//socket.RemoteEndPoint.ToString()是客戶端IP地址 socket.Close(); } }, null); } AsynReceive()4.異步發送方法public void AsynSend()
public void AsynSend(string msg) { byte[] data = Encoding.UTF8.GetBytes(msg); socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult => { int length = socket.EndSend(asyncResult); Console.WriteLine("message send to {0} successfully", socket.RemoteEndPoint.ToString()); }, null); } public void AsynSend(string msg)因為socket收發都是采用字節流的形式,所以接收需要用byte[] data = new byte[1024],緩存收到的字節流,然後通過Encoding.ASCII.GetString(data, 0, length)方法把字節流轉化為字符串輸出;發送通過byte[] data = Encoding.UTF8.GetBytes(msg),把字符串信息轉化為字節流發送。EndReceive(),EndSend()方法返回的都是收發字節數(int)
以上都是最簡單的,只能實現基本的通信功能,後期會在此基礎上完善,幫助初學者少走彎路,我當時可是學的頭昏眼花-_-||
下篇是采用與服務器完全不同模式的客戶端,同步模式