在上一篇中已經介紹了利用Socket建立服務端和客戶端進行通信,如果需要 的朋友可訪問《Socket網絡編程學習筆記(2):面向連接的Socket》。在本篇 中,將利用C#套接字的助手類來簡化Socket編程,使得剛剛接觸到網絡編程的 朋友們更容易上手。
跟上篇一樣,通過C#套接字的助手類來編程同樣分 服務端和客戶端。
一、服務端偵聽模式
1、創建套接字與 IPEndPoint綁定,並設置為偵聽模式。
1//創建IPEndPoint實例
2 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6001);
3 /**//*
4 //創建一個套接字
5 serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
6 //將所創建的套 接字與IPEndPoint綁定
7 serverSocket.Bind(ipep);
8 //設置套接字為收聽模式
9 serverSocket.Listen(10);
10 */
11 serverTcp = new TcpListener(ipep);
12 serverTcp.Start ();
其中注釋掉的部分是利用Socket來創建偵聽,這裡我們可以 看到用套接字助手類只通過二行就可以建立起偵聽,而且如果要更方便一些,可 以不指定IPEndPoint,單單指定端口就可以了,如:
1serverTcp = new TcpListener(6001);
2 serverTcp.Start ();
2、偵聽並獲取接入的客戶Socket連接
1while (true)
2 {
3 try
4 {
5 //在套接字上接收接入的連接
6 //clientSocket = serverSocket.Accept();
7 clientTcp = serverTcp.AcceptTcpClient();
8 clientThread = new Thread(new ThreadStart (ReceiveData));
9 clientThread.Start();
10 }
11 catch (Exception ex)
12 {
13 MessageBox.Show ("listening Error: " + ex.Message);
14 }
15 }
在這裡用clientTcp = serverTcp.AcceptTcpClient();來接收連接的TcpClient對象,我們了可以通過
1clientSocket = serverTcp.AcceptSocket();
來 接收一個Socket對象,如果接收的是一個Socket對象,那麼接下來的接收和發送 信息跟上篇一樣,如果接收的是TcpClient對象,那麼我們來看一下如何來接收 和發送信息:
3 、接收和發送信息
1private void ReceiveData()
2 {
3 bool keepalive = true;
4 TcpClient s = clientTcp;
5 NetworkStream ns = s.GetStream();
6 Byte[] buffer = new Byte[1024];
7
8 //根據收聽到的客戶端套接字向 客戶端發送信息
9 IPEndPoint clientep = (IPEndPoint) s.Client.RemoteEndPoint;
10 lstServer.Items.Add ("Client:" + clientep.Address + " ("+clientep.Port+")");
11 string welcome = "Welcome to my test sever ";
12 byte[] data = new byte[1024];
13 data = Encoding.ASCII.GetBytes(welcome);
14 //s.Send(data, data.Length, SocketFlags.None);
15 ns.Write(data,0, data.Length);
16
17 while (keepalive)
18 {
19 //在套接字上接收客戶端發送的信息
20 int bufLen = 0;
21 try
22 {
23 bufLen = s.Available;
24 //s.Receive(buffer, 0, bufLen, SocketFlags.None);
25 ns.Read(buffer, 0, bufLen);
26 if (bufLen == 0)
27 continue;
28 }
29 catch (Exception ex)
30 {
31 MessageBox.Show("Receive Error:" + ex.Message);
32 return;
33 }
34 clientep = (IPEndPoint)s.Client.RemoteEndPoint;
35 string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen);
36
37 lstServer.Items.Add(clientcommand + "("+clientep.Address + ":"+clientep.Port+") ");
38
39 }
40
41 }
通過NetworkStream ns = s.GetStream();可以獲取網絡流 對象,以此來發送和接收信息。
二、客戶端連接
1、創建套接字 並連接到服務器
1 //創建一個套接字
2 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse ("127.0.0.1"), 6001);
3 //clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
4 clientTcp = new TcpClient();
5
6 //將套接字與遠程服務器地址相連
7 try
8 {
9 //clientSocket.Connect(ipep);
10 clientTcp.Connect(ipep);
11 }
12 catch (SocketException ex)
13 {
14 MessageBox.Show("connect error: " + ex.Message);
15 return;
16 }
2、接收服務器發 送的信息
1ns = clientTcp.GetStream();
2 while (true)
3 {
4 //接收服務器信 息
5 int bufLen = 0;
6 try
7 {
8 //bufLen = clientSocket.Available;
9 bufLen = clientTcp.Available;
10
11 //clientSocket.Receive(data, 0, bufLen, SocketFlags.None);
12 ns.Read(data, 0, bufLen);
13 if (bufLen == 0)
14 {
15 continue;
16 }
17 }
18 catch (Exception ex)
19 {
20 MessageBox.Show("Receive Error:" + ex.Message);
21 return;
22 }
23
24 string clientcommand = System.Text.Encoding.ASCII.GetString(data).Substring(0, bufLen);
25
26 lstClient.Items.Add(clientcommand);
27
28 }
同服務端,通過ns = clientTcp.GetStream();獲取網絡流來讀取服務端發過來的信息。
3、向 服務端發送信息
1//向服務器發送信息
2
3 byte[] data = new byte[1024];
4 data = Encoding.ASCII.GetBytes(txtClient.Text);
5 //clientSocket.Send(data, data.Length, SocketFlags.None);
6 ns.Write(data, 0, data.Length);
到這裡,我們就可 以實現客戶端與服務端的連接和通訊了。一些方法跟上一篇提到的類似,這裡就 不再詳述。
接下來,我會講一下關於Socket發送的消息邊界處理問題、 發送實體類數據問題以及利用線程池來改善線程創建和分配問題。
本文配套源碼