首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++Builder Socket API 實作 TCP/UDP 雙模式客戶端與伺服器完整範例

     編輯:關於C++

前言:從 VCL 元件轉向原生 Socket API

許多 C++Builder 開發者習慣使用 TClientSocket/TServerSocket 等 VCL 封裝元件。但若需精細控制連線行為、支援非同步事件、或移植至非 VCL 專案,直接呼叫 Winsock API (socket, bind, connect, send, recv 等) 更具彈性。本文整理一套完整、經除錯的 TCP/UDP 雙模式客戶端與伺服器 原始碼,採用 C++Builder 專案結構,包含非同步事件通知、多執行緒監聽、錯誤處理等實務技巧。

專案架構概覽

  • Client 端:單一表單,含協定選擇 (TCP/UDP)、IP/Port 設定、發送/接收顯示區,使用 WSAAsyncSelect 實現視窗訊息驅動的非同步通知。
  • Server 端:採雙執行緒架構——TListenThread 負責監聽/接受連線 (TCP) 或接收資料包 (UDP);TCommunication 執行緒處理每個 TCP 客戶端的收發邏輯 (Echo 回傳)。

核心程式碼精要 (Client 端)

1. 非同步事件處理

// 訊息對應表
#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;
    }
}

2. 連線與發送流程

  • 初始化 Winsock (WSAStartup)
  • 建立 Socket (socket(AF_INET, SOCK_STREAM/DGRAM, 0))
  • 綁定本地任意 Port (bind)
  • TCP: connect + select 確認連線完成;UDP: 直接 sendto
  • 註冊非同步事件 (WSAAsyncSelect(hWnd, WM_SOCK, FD_READ|FD_CLOSE))

核心程式碼精要 (Server 端)

1. 監聽執行緒 (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
            }
        }
    }
}

2. 通訊執行緒 (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 專案選項中自動處理)。
  • Server 端啟動後點擊「啟動監聽」按鈕 (Button2),Client 端輸入 Server IP/Port 並點選「連線發送」。
  • 防火牆需允許該埠號通訊。

結語

此範例展示了 Winsock API 在 C++Builder 中的完整實戰應用,涵蓋 TCP/UDP 雙協定、非同步事件、多執行緒伺服器架構。開發者可據此擴充協定解析、封包重組、SSL/TLS 加密、IOCP 高效能模型等進階功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved