簡介
TCP 是一個連線導向的網路傳輸協定,程式通常在斷線之前會一直記住這個連線。在我們使用 Socket 函式庫設計 TCP 網路程式時,通常會讓一個 Thread 負責處理一條連線,這樣可以讓問題變得較為單純,因為不需要用表格去記住連線。
所以,在學習 TCP 程式設計之前,我們有必要先複習一下 Thread (台灣稱為執行緒、中國大陸稱為線程) 的程式設計方式,若讀者對 Thread 尚不熟悉,請讀者先看完下列兩篇文章後再回到此處閱讀。
TCP 的程式架構
TCP 客戶端的通常在連上伺服端後,就會用一個迴圈透過 Socket.send 函數傳送訊息,以下是一個典型的 TCP 客戶端程式。
客戶端:Client
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(address), port);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Connect(ip);
...
while(true) {
...
server.Send(data);
...
}
...
server.Shutdown(SocketShutdown.Both);
server.Close();
TCP 伺服端通常較為複雜,首先在利用 Socket 中的 bind() 函數佔用特定的 port 之後,會再進入一個無窮迴圈,在迴圈中利用 socket.Accept() 接受客戶端的連線,此時會產生一個新的 Socket 物件。通常,我們會建立一個新的 Thread 去處理這個連線,因此在下列程式中,我們建立了 TcpListener 這個物件,以便讓一個 Listener 處理一個 Socket 連線。
伺服端:Server
public class TcpServer
{
public static void Main()
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ip);
socket.Listen(10);
while(true)
{
Socket client = socket.Accept();
TcpListener listener = new TcpListener(client); // 建立 Listener 物件處理這個連線。
Thread thread = new Thread(new ThreadStart(listener.run)); // 建立 listener.run 的 Thread。
thread.Start(); // 啟動 Thread
...
}
...
}
}
public class TcpListener {
Socket socket;
public TcpListener(Socket s) { socket = s; }
public void run() { // Thread 的主要函數
while (true) {
...
byte[] data = new byte[1024];
int recv = socket.Receive(data); // 接收資料
...
}
socket.Close();
}
}
結語
以上就是一個典型的 TCP 程式架構,該架構包含了『客戶端-伺服端』兩個部分,客戶端透過 Socket.send 傳送訊息,而伺服端則會針對每一個連線,建立新的 Thread ,以便處理連線的互動關係。這種架構對 TCP 而言是較為簡單的,有幾個連線就建立幾個 Thread。由於這種架構不需要用表格記住連線,因此簡化了伺服端的管理,讓程式設計更為容易。
在理解了這個架構後,您可以看看真實的程式範例,以下是筆者所撰寫的幾個相關程式,敬請參考。
- TCP : 單向的訊息傳遞程式
- TCP : 雙向的P2P聊天程式
- TCP : 多人聊天室
陳鍾誠 (2010年06月15日),(網頁標題) TCP 網路程式設計,(網站標題) 免費電子書:C# 程式設計,2010年06月15日,取自 http://cs0.wikidot.com/tcp ,網頁修改第 0 版。