這兩天在學習C#,C#高級編程真的是厚厚的一本書QAQ。 昨天看了一下裡面的通信部分(其實還沒怎麼看),看了網上一些人的博客,自己在他們的博客基礎上寫了一個通信。 先來講述下我自己對於整個Socket通信過程的理解,畢竟初學,說錯見諒,知道錯了會改正~ 首先在服務端新建一個serverSocket, ...
這兩天在學習C#,C#高級編程真的是厚厚的一本書QAQ。
昨天看了一下裡面的通信部分(其實還沒怎麼看),看了網上一些人的博客,自己在他們的博客基礎上寫了一個通信。
先來講述下我自己對於整個Socket通信過程的理解,畢竟初學,說錯見諒,知道錯了會改正~
首先在服務端新建一個serverSocket,對其進行初始化(一般包含AddressFamily:IP地址類型,SocketType:Socket傳輸數據方式,ProtoType:傳輸協議);
接著我們要設置server端要綁定的IP:port;然後開始監聽,並設置最多同時監聽多少個Client.
這時,服務端就在等待狀態,直到某一個Client連接到這個ip:port上,這時serverSocket.Accept()工作,獲得這個連接。(此時的連接是有地址信息的哦!記得保存)
獲得連接之後,server就可以和這個Client進行通信了,當加入第二個Client(我們稱其為ClientB)時,Server接收到ClientB的消息,可以將這個消息轉發給前一個Client(我們稱其為ClientA),當受到ClientA的消息,也可以轉發給ClientB。這樣就實現了Clients之間的通信了。(重點在保存連接信息!!)
那麼現在貼上代碼講解:
Server端代碼
1 namespace SocketServer 2 { 3 class Program 4 { 5 private static byte[] result = new byte[1024]; 6 7 static Socket serverSocket; 8 private static string client; 9 private static Socket clientSocket; 10 //我這裡存了兩個Client,因為自己電腦開了兩個Client,不會有多的 11 //理論上應該開一個Socket[]來保存信息,最好用一個二元組將client的信息和連接綁定起來 12 //這樣就可以實現斷開連接後下次登陸還是可以識別是這個Client 13 private static Socket clientSocketA=null; 14 private static Socket clientSocketB=null; 15 16 static void Main(string[] args) 17 { 18 Program.SetPort(8885); 19 } 20 private static void SetPort(int port) 21 { 22 IPAddress ip = IPAddress.Parse("127.0.0.1");//set ip 23 serverSocket = new Socket(AddressFamily.InterNetwork, 24 SocketType.Stream, ProtocolType.Tcp);//initialize 25 serverSocket.Bind(new IPEndPoint(ip, port));//bind 26 serverSocket.Listen(10); 27 //進入監聽狀態 28 Console.WriteLine("監聽{0}成功", serverSocket.LocalEndPoint.ToString()); 29 //開啟一個線程來監聽客戶端連接 30 Thread myThread = new Thread(ListenClientConnect); 31 myThread.Start(); 32 Console.ReadLine(); 33 34 } 35 /// <summary> 36 /// 監聽客戶端連接 37 /// </summary> 38 private static void ListenClientConnect() 39 { 40 while (true) 41 { 42 //Client連接上後 得到這個連接 43 clientSocket = serverSocket.Accept(); 44 45 //這裡我因為只有兩個Client,所以就簡單寫了 46 if (clientSocketA == null) 47 { 48 clientSocketA = clientSocket; 49 } 50 else if (clientSocketB == null) 51 { 52 clientSocketB = clientSocket; 53 } 54 else 55 { 56 //當其中一個斷開了,又重新連接時,需要再次保存連接 57 if (clientSocketB.IsBound) 58 { 59 clientSocketA = clientSocketB; 60 clientSocketB = clientSocket; 61 } 62 else 63 { 64 clientSocketB = clientSocketA; 65 clientSocketA = clientSocket; 66 } 67 68 } 69 clientSocket.Send(Encoding.ASCII.GetBytes("say hello")); 70 //開個線程接收Client信息 71 Thread receivedThread = new Thread(ReceiveMessage); 72 receivedThread.Start(clientSocket); 73 74 } 75 } 76 77 private static void ReceiveMessage(object clientSocket) 78 { 79 Socket myClientSocket = (Socket) clientSocket; 80 81 while (true) 82 { 83 try 84 { 85 int revceiveNumber = myClientSocket.Receive(result); 86 //Console.WriteLine("接受客戶端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString() 87 // , Encoding.ASCII.GetString(result, 0, revceiveNumber)); 88 Console.WriteLine(Encoding.ASCII.GetString(result, 0, revceiveNumber)); 89 if (myClientSocket == clientSocketA) 90 { 91 Console.WriteLine("receive from A"); 92 if (clientSocketB!=null&&clientSocketB.IsBound) 93 { 94 Console.WriteLine("a IS BOUND"); 95 clientSocketB.Send(result, 0, revceiveNumber, SocketFlags.None); 96 } 97 else 98 { 99 myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!")); 100 Console.WriteLine("對方不線上上,發送失敗!"); 101 } 102 } 103 else 104 { 105 Console.WriteLine("receive from B"); 106 if (clientSocketA != null && clientSocketA.IsBound) 107 { 108 Console.WriteLine("a IS BOUND"); 109 clientSocketA.Send(result, 0, revceiveNumber, SocketFlags.None); 110 } 111 else 112 { 113 myClientSocket.Send(Encoding.ASCII.GetBytes("the people is not online! Send Failed!")); 114 Console.WriteLine("對方不線上上,發送失敗!"); 115 } 116 117 } 118 119 } 120 catch(Exception ex) 121 { 122 Console.WriteLine(ex.Message); 123 myClientSocket.Shutdown(SocketShutdown.Both); 124 myClientSocket.Close(); 125 break; 126 127 } 128 } 129 130 } 131 } 132 }
Client端代碼(因為都差不多 就只貼一個了)
1 namespace SocketClient 2 { 3 class Program 4 { 5 private static byte[] result = new byte[1024]; 6 private static Socket clientSocket; 7 private static void ListenServer() 8 { 9 while (true) 10 { 11 result = new byte[1024]; 12 int receiveLength = clientSocket.Receive(result); 13 14 Console.WriteLine("{0}", Encoding.ASCII.GetString(result, 0, receiveLength)); 15 } 16 17 } 18 static void Main(string[] args) 19 { 20 21 IPAddress ip = IPAddress.Parse("127.0.0.1"); 22 clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 23 try 24 { 25 clientSocket.Connect(ip, 8885); 26 Console.WriteLine("連接成功!"); 27 28 } 29 catch (Exception e) 30 { 31 Console.WriteLine("連接失敗!"); 32 return; 33 } 34 Thread threadRead = new Thread(ListenServer); 35 threadRead.Start(); 36 37 38 while(true) 39 { 40 try 41 { 42 Thread.Sleep(1000); 43 string sendMessage = Console.ReadLine(); 44 clientSocket.Send(Encoding.ASCII.GetBytes("Sylvia:"+sendMessage)); 45 46 } 47 catch (Exception ex) 48 { 49 clientSocket.Shutdown(SocketShutdown.Both); 50 clientSocket.Close(); 51 break; 52 } 53 54 } 55 Console.WriteLine("發送完畢 按回車退出"); 56 Console.ReadKey(); 57 } 58 } 59 }
寫的時候要特別註意一下Send信息的時候,註意byte[]的傳輸大小,很容易變成byte[]數組的大小而不是內容的大小。
這個大家就自己嘗試吧