本文提供完整、可編譯執行的 C++ Builder 專案原始碼,實現同時支援 TCP 與 UDP 的客戶端與伺服器。架構採用非阻塞 Socket + WSAAsyncSelect 事件通知 (客戶端) 與多執行緒 accept/recvfrom 迴圈 (伺服器),展示專業級網路程式設計範式。
enum PROTO { TCP = 0, UDP = 1 };
#define WM_SOCK WM_USER + 100 // 自定義視窗訊息
const int MAX_BUF = 4096;
class TLANForm : public TForm {
// UI 元件:Port, Prot(TCP/UDP), Addr(IP), TxtEdit(收發顯示), Button1(送出)
SOCKET m_Socket; // 通訊 Socket
PROTO m_Protocol; // 目前協定
// 訊息映射
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_SOCK, TMessage, OnRecv)
END_MESSAGE_MAP(TForm)
};
WSAStartup(MAKEWORD(2,0)) 初始化 Winsock 2.0socket(AF_INET, SOCK_STREAM/DGRAM, 0)connect + select 確認連線建立send (TCP) / sendto (UDP)WSAAsyncSelect(m_Socket, Handle, WM_SOCK, FD_READ | FD_CLOSE) 註冊非阻塞事件通知void __fastcall TLANForm::OnRecv(TMessage &Message) {
switch (WSAGETSELECTEVENT(Message.LParam)) {
case FD_READ:
// TCP: recv / UDP: recvfrom
// 更新 TxtEdit 顯示
break;
case FD_CLOSE:
closesocket(m_Socket);
break;
}
}
socket/bind/listen (TCP) 或 recvfrom 迴圈 (UDP)accept 產生一個工作執行緒處理單一客戶端收發void __fastcall TListenThread::Execute() {
InitSocket(); // WSAStartup
CreateListenSocket(); // socket() 依協定
SetListenSocket(); // setsockopt SO_OPENTYPE
BindListenSocket(); // bind(INADDR_ANY, Port)
if (m_Protocol == UDP) {
// UDP 直接收發迴圈
while (!Terminated) {
nSize = recvfrom(m_Socket, buf, ..., &from, &nLen);
if (nSize > 0) { 顯示; sendto(回傳); }
}
} else {
ListenSocket(); // listen(SOMAXCONN)
FD_ZERO(&FDS); FD_SET(m_Socket, &FDS);
while (!Terminated) {
if (select(1, &FDS, 0, 0, 0) > 0) {
SOCKET client = accept(m_Socket, ...);
TCommunication *t = new TCommunication(client, FALSE);
t->WaitFor(); // 同步等待處理完成 (示範用,實際應非同步)
}
}
}
}
void __fastcall TCommunication::Execute() {
nSize = recv(m_AcceptSocket, buf, 4096, 0);
if (nSize > 0) {
buf[nSize] = '\0';
// 顯示於主視窗 Memo1 (需同步)
Sleep(100); // 模擬處理延遲
send(m_AcceptSocket, buf, nSize, 0); // Echo 回傳
}
}
| 面向 | 客戶端 | 伺服器 |
|---|---|---|
| I/O 模型 | WSAAsyncSelect 事件驅動 (單執行緒) | 多執行緒 + select/阻塞呼叫 |
| UDP 處理 | sendto/recvfrom 配合 FD_READ | 監聽執行緒直接 recvfrom 迴圈 |
| TCP 連線 | connect + select 非阻塞確認 | listen + accept 產生工作執行緒 |
| 資源清理 | FormDestroy: closesocket + WSACleanup | 執行緒析構: closesocket + WSACleanup |
| 錯誤處理 | WSAGetLastError 彈出訊息框 | DoError 統一清理 + 訊息框 |
AF_INET6 + getaddrinfo 同時支援 IPv4/IPv6此代碼為教學示範,實際專案請依上述清單工程化重構。