Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux TCP 服務器與客戶端實作完整教學(含程式碼範例)

編輯:Linux 教學

前言

在 Linux 環境下開發網路應用程式時,Socket 程式設計是核心基礎。本文將完整示範如何使用 C 語言實作一個簡單的 TCP 服務器與客戶端,涵蓋從建立 Socket、綁定位址、監聽連線、資料收發到關閉連線的完整流程,並提供可直接編譯執行的程式碼與執行結果說明。

一、TCP 服務器端程式實作

1. 表頭檔案與常數定義

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PORTNUMBER 3333  // 服務器與客戶端連接埠必須一致

2. 主程式流程

int main(int argc, char *argv[]) {
    int sockfd, new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int sin_size;
    int nbytes;
    char buffer[1024];

    /* 建立 Socket 描述符 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "Socket error:%s\n\a", strerror(errno));
        exit(1);
    }

    /* 填充 sockaddr_in 結構 */
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // 綁定所有本地 IP
    server_addr.sin_port = htons(PORTNUMBER);

    /* 綁定 Socket 到 IP 與連接埠 */
    if (bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) {
        fprintf(stderr, "Bind error:%s\n\a", strerror(errno));
        exit(1);
    }

    /* 設定最大連線佇列長度 */
    if (listen(sockfd, 5) == -1) {
        fprintf(stderr, "Listen error:%s\n\a", strerror(errno));
        exit(1);
    }

    /* 進入無限迴圈等待客戶端連線 */
    while (1) {
        sin_size = sizeof(struct sockaddr_in);
        if ((new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1) {
            fprintf(stderr, "Accept error:%s\n\a", strerror(errno));
            exit(1);
        }
        fprintf(stderr, "Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));

        /* 讀取客戶端傳送的資料 */
        if ((nbytes = read(new_fd, buffer, 1024)) == -1) {
            fprintf(stderr, "Read Error:%s\n", strerror(errno));
            exit(1);
        }
        buffer[nbytes] = '\0';
        printf("Server received: %s\n", buffer);

        /* 關閉此次連線,繼續等待下一個 */
        close(new_fd);
    }

    close(sockfd);
    return 0;
}

二、TCP 客戶端程式實作

1. 表頭檔案與參數檢查

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define PORTNUMBER 3333

int main(int argc, char *argv[]) {
    int sockfd;
    char buffer[1024];
    struct sockaddr_in server_addr;
    struct hostent *host;

    /* 必須提供主機名稱作為參數 */
    if (argc != 2) {
        fprintf(stderr, "Usage:%s hostname \a\n", argv[0]);
        exit(1);
    }

    /* 解析主機名稱 */
    if ((host = gethostbyname(argv[1])) == NULL) {
        fprintf(stderr, "Gethostname error\n");
        exit(1);
    }

2. 建立連線與傳送資料


    /* 建立 Socket */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "Socket Error:%s\a\n", strerror(errno));
        exit(1);
    }

    /* 填充伺服器端資訊 */
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORTNUMBER);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);

    /* 發起連線請求 */
    if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) {
        fprintf(stderr, "Connect Error:%s\a\n", strerror(errno));
        exit(1);
    }

    printf("Please input char:\n");
    fgets(buffer, 1024, stdin);
    write(sockfd, buffer, strlen(buffer));  // 也可用 send()

    close(sockfd);
    return 0;
}

三、編譯與執行驗證

伺服器端編譯:

gcc tcp_server.c -o tcp_server

客戶端編譯(以 ARM 交叉編譯為例):

arm-hismall-linux-gcc tcp_client.c -o tcp_hiclient

執行結果示意:

伺服器端執行畫面

客戶端執行畫面

四、關鍵點總結

  • Socket 類型:使用 SOCK_STREAM 代表 TCP 可靠串流傳輸。
  • 位址轉換:htonl/htons 將主機位元組序轉為網路位元組序。
  • INADDR_ANY:讓服務器監聽所有網卡介面。
  • 阻塞模式:accept、read 預設為阻塞,直到有連線或資料到達。
  • 資源釋放:每次通訊結束需 close(new_fd),最終關閉 sockfd。
Copyright © Windows教程網 All Rights Reserved