本文實作一個基於 TCP 的點對點聊天小程式,展示 socket、fork 多進程並發、signal 進程同步退出的核心網路程式設計技術。
accept 連線後 fork 子進程。
read 接收客戶端訊息並輸出。fgets 讀取標準輸入並 write 發送。fork 兩進程分工收發。
read 返回 0),以 SIGUSR1 殺死對應進程,雙向清理。int listenfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
listen(listenfd, SOMAXCONN);
int conn = accept(listenfd, (SA*)&peeraddr, &socklen);
pid_t pid = fork();
if (pid == 0) { // 子進程:發送
signal(SIGUSR1, handler);
while (fgets(sendbuf, sizeof(sendbuf), stdin))
write(conn, sendbuf, strlen(sendbuf));
exit(0);
} else { // 父進程:接收
while (read(conn, recvbuf, sizeof(recvbuf)) > 0)
fputs(recvbuf, stdout);
kill(pid, SIGUSR1); // 通知子進程退出
exit(0);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, (SA*)&servaddr, sizeof(servaddr));
pid_t pid = fork();
if (pid == 0) { // 子進程:接收
while (read(sockfd, recvbuf, sizeof(recvbuf)) > 0)
fputs(recvbuf, stdout);
kill(getppid(), SIGUSR1);
} else { // 父進程:發送
signal(SIGUSR1, handler);
while (fgets(sendbuf, sizeof(sendbuf), stdin))
write(sockfd, sendbuf, strlen(sendbuf));
}
fork 實現雙工通訊:單進程難以同時阻塞於 read (網路) 與 fgets (標準輸入),雙進程分工解決。read 返回值語義:>0 收到資料,=0 對方關閉連線(EOF),=-1 錯誤。SIGUSR1 自訂訊號:用於進程間通知退出,避免殭屍進程。SO_REUSEADDR:允許 Server 重啟時立即重用埠,避免 TIME_WAIT 等待。gcc server.c -o server
gcc client.c -o client
# 終端 1
./server
# 終端 2
./client
# 雙向輸入文字即可聊天,Ctrl+D 或關閉視窗退出
select/poll/epoll 替代多進程,支援高併發。