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


SOCK_STREAM 代表 TCP 可靠串流傳輸。htonl/htons 將主機位元組序轉為網路位元組序。accept、read 預設為阻塞,直到有連線或資料到達。close(new_fd),最終關閉 sockfd。Linux 開機自動啟動腳本配置完整指南:chkconfig 與 systemd 實戰
C# DateTime 格式化大全:標準/自定義格式字串、GMT/RFC1123、常用 ToString 模式速查
AMH 面板驗證碼持續報錯排查:磁碟空間耗盡導致 Session 無法寫入
Ubuntu 創辦人宣稱:企業級 Linux 不只有 Red Hat
Linux下Oracle靜默安裝完整指南:Response File與DBCA模板實戰
Windows 與 Linux 動態函式庫深度解析:DLL 與 SO 移植實戰指南