許多 C++Builder 開發者習慣使用 TClientSocket/TServerSocket 等 VCL 封裝元件。但若需精細控制連線行為、支援非同步事件、或移植至非 VCL 專案,直接呼叫 Winsock API (socket, bind, connect, send, recv 等) 更具彈性。本文整理一套完整、經除錯的 TCP/UDP 雙模式客戶端與伺服器 原始碼,採用 C++Builder 專案結構,包含非同步事件通知、多執行緒監聽、錯誤處理等實務技巧。
WSAAsyncSelect 實現視窗訊息驅動的非同步通知。TListenThread 負責監聽/接受連線 (TCP) 或接收資料包 (UDP);TCommunication 執行緒處理每個 TCP 客戶端的收發邏輯 (Echo 回傳)。// 訊息對應表
#define WM_SOCK WM_USER + 100
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_SOCK, TMessage, OnRecv)
END_MESSAGE_MAP(TForm)
// 接收處理
void __fastcall TLANForm::OnRecv(TMessage &Message)
{
char buf[4096]; int nLen;
sockaddr_in from; int nLength = sizeof(from);
switch (WSAGETSELECTEVENT(Message.LParam))
{
case FD_READ:
switch (m_Protocol)
{
case TCP: nLen = recv(m_Socket, buf, 4096, 0); break;
case UDP: nLen = recvfrom(m_Socket, buf, 4096, 0, (sockaddr*)&from, &nLength); break;
}
if (nLen > 0) { buf[nLen] = '\0'; TxtEdit->Text = "Received: " + String(buf); }
break;
case FD_CLOSE:
closesocket(m_Socket);
break;
}
}
WSAStartup)socket(AF_INET, SOCK_STREAM/DGRAM, 0))bind)connect + select 確認連線完成;UDP: 直接 sendtoWSAAsyncSelect(hWnd, WM_SOCK, FD_READ|FD_CLOSE))TListenThread)void __fastcall TListenThread::Execute()
{
InitSocket(); CreateListenSocket(); SetListenSocket(); BindListenSocket();
if (m_Protocol == UDP) {
// UDP 迴圈:recvfrom -> 處理 -> sendto 回覆
while (!Terminated) { ... }
} else {
// TCP: listen -> select 等待連線 -> accept -> 建立 TCommunication 執行緒
ListenSocket();
while (!Terminated) {
if (select(1, &FDS, 0, 0, 0) > 0) {
SOCKET client = accept(m_Socket, ...);
new TCommunication(client, FALSE); // FreeOnTerminate=true
}
}
}
}
TCommunication)void __fastcall TCommunication::Execute()
{
char buf[4096];
int nSize = recv(m_AcceptSocket, buf, 4096, 0);
if (nSize > 0) {
buf[nSize] = '\0';
// 顯示於主表單 Memo (需執行緒安全,範例簡化直接存取)
PSTNForm->Memo1->Lines->Add("Received: " + String(buf));
Sleep(100);
send(m_AcceptSocket, buf, nSize, 0); // Echo 回傳
}
}
| 項目 | 說明 |
|---|---|
| 非同步模型 | Client 端採 WSAAsyncSelect 視窗訊息;Server 端採 select + 多執行緒 |
| 協定切換 | 透過 enum PROTO {TCP, UDP} 統一控制流程分支 |
| 錯誤處理 | 每步 API 呼叫檢查回傳值,WSAGetLastError() 取得錯誤碼,彈出訊息框並清理資源 |
| 資源管理 | 執行緒 FreeOnTerminate=true,FormDestroy 呼叫 closesocket + WSACleanup |
| 緩衝區大小 | 固定 4096 Bytes,超過則截斷或報錯 |
ws2_32.lib (C++Builder 專案選項中自動處理)。此範例展示了 Winsock API 在 C++Builder 中的完整實戰應用,涵蓋 TCP/UDP 雙協定、非同步事件、多執行緒伺服器架構。開發者可據此擴充協定解析、封包重組、SSL/TLS 加密、IOCP 高效能模型等進階功能。