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

Linux C 語言 TCP 服務器/客戶端完整實現指南

     編輯:關於C

前言

基於 BSD Socket API 實現 TCP 通信是網絡編程入門必修課。本文提供可直接編譯運行的服務端/客戶端完整代碼,涵蓋錯誤處理、地址轉換、循環服務等生產級要素。

一、客戶端代碼

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 3333
#define BUFSIZE 1024

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s \n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* 1. 創建 Socket */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    /* 2. 解析服務器地址 */
    struct hostent *host = gethostbyname(argv[1]);
    if (!host) {
        herror("gethostbyname");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    /* 3. 填充 sockaddr_in */
    struct sockaddr_in server_addr = {0};
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr = *(struct in_addr *)host->h_addr_list[0];

    /* 4. 發起連接 */
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connect");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    printf("Connected to %s:%d\n", inet_ntoa(server_addr.sin_addr), PORT);

    /* 5. 發送數據 */
    char buffer[BUFSIZE];
    printf("Enter message: ");
    if (fgets(buffer, BUFSIZE, stdin)) {
        send(sockfd, buffer, strlen(buffer), 0);
    }

    /* 6. 關閉 */
    close(sockfd);
    return 0;
}

二、服務端代碼

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 3333
#define BACKLOG 5
#define BUFSIZE 1024

int main() {
    /* 1. 創建監聽 Socket */
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1) { perror("socket"); exit(EXIT_FAILURE); }

    /* 2. 設置地址復用,避免 TIME_WAIT 干擾重啟 */
    int opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    /* 3. 綁定地址 */
    struct sockaddr_in server_addr = {0};
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // 監聽所有網卡
    server_addr.sin_port = htons(PORT);

    if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        close(listenfd);
        exit(EXIT_FAILURE);
    }

    /* 4. 監聽 */
    if (listen(listenfd, BACKLOG) == -1) {
        perror("listen");
        close(listenfd);
        exit(EXIT_FAILURE);
    }
    printf("Server listening on port %d...\n", PORT);

    /* 5. 主循環接受連接 */
    while (1) {
        struct sockaddr_in client_addr;
        socklen_t addrlen = sizeof(client_addr);
        int connfd = accept(listenfd, (struct sockaddr *)&client_addr, &addrlen);
        if (connfd == -1) {
            perror("accept");
            continue;  // 不退出主循環
        }
        printf("Client connected: %s:%d\n",
               inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        /* 6. 接收數據 */
        char buffer[BUFSIZE];
        ssize_t n = recv(connfd, buffer, BUFSIZE - 1, 0);
        if (n > 0) {
            buffer[n] = '\0';
            printf("Received: %s\n", buffer);
        } else if (n == 0) {
            printf("Client closed connection\n");
        } else {
            perror("recv");
        }

        /* 7. 關閉本次連接 */
        close(connfd);
    }

    close(listenfd);  // 理論不可達
    return 0;
}

三、編譯與運行

# 服務端
gcc server.c -o server
./server

# 客戶端(另開終端)
gcc client.c -o client
./client 127.0.0.1

四、關鍵 API 說明

函數作用關鍵參數
socket創建通信端點AF_INET(IPv4), SOCK_STREAM(TCP)
bind綁定本地地址INADDR_ANY 監聽所有接口
listen轉為被動監聽backlog 控制已完成連接隊列長度
accept取出已完成連接返回新 socket,原 socket 繼續監聽
connect主動發起連接阻塞直到三次握手完成
send/recv數據收發flags=0 普通;MSG_NOSIGNAL 忽略 SIGPIPE
htons/htonl主機序轉網絡序(大端)端口、IPv4 地址必須轉換

五、進階擴展方向

  • 並發處理:fork() 多進程 / pthread 多線程 / select/poll/epoll I/O 多路復用
  • 優雅關閉:捕獲 SIGINT/SIGTERM,關閉監聽套接字,等待子進程/線程退出
  • 協議設計:定長包頭 + 變長體、心跳檢測、重連邏輯
  • SSL/TLS:集成 OpenSSL 實現加密傳輸

六、總結

掌握 socket → bind → listen → accept 服務端五步驟與 socket → connect 客戶端兩步驟,並熟練處理錯誤碼、字節序、地址轉換,是 Linux C 網絡編程的基石。本文代碼經實測可直接在 Ubuntu/CentOS/macOS 上運行,建議作為項目模板擴展。

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