簡述
連線導向服務(TCP)的主要特點有:
- 資料轉送必須經過建立、維護和釋放三個階段
- 在傳輸過程中,個分組不需要攜帶目的主機的地址
- 可靠性好,但協議複雜,通訊效率不高
面向無串連服務(UDP)的主要特點:
- 不需要串連的各個階段
- 各個分組要攜帶完整的目的主機地址,在系統中獨立傳送
- 由於沒有順序控制,所以接收方的分組可能出現亂序,重複和丟失現象
- 通訊效率高,但不能確保可靠性 Socket類的基本使用 Socket類的建立
Socket類的建構函式原型為:
public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType)
對於常規IP通訊,AddressFamily只能使用AddressFamily、InetNetwork、SocketType參數需要和ProtocolType配合使用
通訊端的組合方式
| SocketType |
ProtocolType |
說明 |
| Dgram |
Udp |
不需連線的通訊 |
| Stream |
Tcp |
連線導向的通訊 |
| Raw |
Icmp |
基於ICMP協議的通訊 |
| Raw |
Raw |
簡單IP包的通訊 |
流式通訊端的建立執行個體
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
資料通訊端的建立執行個體
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
原始通訊端的建立執行個體
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
這裡要注意學習socket的常用屬性,通過這些可以設定或者擷取資訊 Bind(EndPoint address)
對於伺服器程式,通訊端必須綁定到本地IP地址或者連接埠上,明確本地半相關 Listen(int backlog)
這個方法只用於連線導向的伺服器方,其參數指出系統等待使用者程式排隊的串連數,即隊列長度。隊列中的串連請求按照先入先出原則,被Accept方法接做接受處理 Accept()
該方法只用於連線導向的伺服器方,進入監聽狀態後,程式執行到該方法會處於暫停狀態,直到有客戶請求串連。一旦有了串連請求,該方法接受請求,並且返回一個新的通訊端對象,該對象包含於該客戶機通訊的所有串連資訊。而最初建立的通訊端仍然只負責監聽,並且在需要的時候電泳Accept方法以接受新的串連請求。
IPHostEntry localHost = Dns.GetHostByName(Dns.GetHostName());IPEndPoint localEP = new IPEndPoint(localHost.AddressList[0],3456);Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);mySocket.Bind(localEP);mySocket.Listen(20);Socket newSocket = mySocket.Accept();//對新產生的newSocket進行新的操作
此時,就可以通過新產生的newSocket進行資料轉送了。
通過對上述語句的修改,可以實現重複服務和並發服務。
並發服務:
for (; ; ) { Socket newSocket = mySocket.Accept(); if(CreateThread()){ mySocket.Close(); //對newSocket操作 } newSocket.Close(); }
重複服務
for (; ; ) { Socket newSocket = mySocket.Accept(); //對newSocket操作 newSocket.Close();}
Connect(EndPoint remoteEP)
這個方法是連線導向調用的客戶方,主動向伺服器發送串連請求,其參數要與伺服器方的IP和連接埠組合。調用Connect後,客戶機通訊端會一直阻塞到串連建立;如果串連不成功,則會返回異常
使用方法:
IPAddress remoteHost = IPAddress.Parse("180.149.132.47");//百度的地址IPEndPoint remoteEP = new IPEndPoint(remoteHost, 80);//設定Socket的類型Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);sock.Connect(remoteEP);
其中remoteEP中指定的IP地址和連接埠號碼必須是伺服器方用於監聽的進程資訊,而不是用戶端的本地節點資訊。 Receive/Send方法
在資料轉送中,流式通訊端使用Receive和Send方法,而資料通訊端將使用ReceiveFrom和SendTo方法。連線導向的通訊端和資料通訊端調用時,其接受和發送方法有多個重載。 Shutdown(SocketShutdown how)和close方法
在通訊完成後,先使用shutdown來禁止該通訊端上的發送和接收,然後使用Close方法關閉通訊端
ShutDown方法的參數取值
| 取值 |
說明 |
| SocketShutdown.Both |
在通訊端上停止發送和接受 |
| SocketShutdown.Receive |
在通訊端上停止接受資料。如果收到額外資料,發出一個RST訊號 |
| SocketShutdown.Send |
在通訊端上停止發送資料。如果所有緩衝區資料都發送完後,發出一個FIN訊號 |
sock.Shutdown(SocketShutdown.Both);sock.Close();
通訊端的簡單應用執行個體
伺服器端的代碼,這個程式需要先啟動
//這個方法是伺服器端,用來接收,必須先啟動Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);IPEndPoint myHost = new IPEndPoint(IPAddress.Parse("192.168.43.81"), 2345);socket.Bind(myHost);socket.Listen(2345);Socket receiveSocket = socket.Accept();byte[] data = new byte[1024];receiveSocket.Receive(data);string str = System.Text.Encoding.Unicode.GetString(data);data = System.Text.Encoding.Unicode.GetBytes("A reply from Server");receiveSocket.Send(data);Console.WriteLine("接收到的資料是:{0},已經發送回複",str);socket.Close();receiveSocket.Close();Console.ReadKey();
這個是用戶端的代碼,需要後啟動
//這個是用戶端,後啟動IPEndPoint serverHost = new IPEndPoint(IPAddress.Parse("192.168.43.81"), 2345);Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socket.Connect(serverHost);byte[] data = new byte[1024];data = System.Text.Encoding.Unicode.GetBytes("Hello this is a example");//發送socket.Send(data);Console.WriteLine("資料已經發送,正在等待接受資料");//接收socket.Receive(data);string str = System.Text.Encoding.Unicode.GetString(data);Console.WriteLine("收到資料,{0}",str);//關閉socket.Shutdown(SocketShutdown.Both);socket.Close();
結束。