該實例摘自《linux網絡編程》(宋敬彬,孫海濱等著)。linux
例子分爲服務器端和客戶端,客戶端鏈接服務器後從標準輸入讀取輸入的字符串,發送給服務器;服務器接收到字符串後,發送給服務器;服務器接收到字符串後統計字符串的長度,而後將該值傳給客戶端;客戶端將接收到的信息打印到標準輸出。編程
1、服務器端代碼服務器
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8888 #define BACKLOG 2 #define LENGTH 1024 void process_conn_server(int s) { int size = 0; char buffer[LENGTH]; for(;;){ size = read(s, buffer, LENGTH); if(size == 0) return; sprintf(buffer, "%d bytes altogether\n", size); write(s, buffer, strlen(buffer)+1); } } int main(int argc, char**argv) { int ss, sc; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int err; pid_t pid; ss = socket(AF_INET, SOCK_STREAM, 0); if(ss < 0){ printf("socket error\n"); return -1; } bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr)); if(err < 0){ printf("bind error\n"); return -1; } err = listen(ss, BACKLOG); if(err < 0){ printf("listen error\n"); return -1; } for(;;){ int addrlen = sizeof(struct sockaddr); sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen); if(sc < 0) continue; pid = fork(); if(pid == 0){ close(ss); process_conn_server(sc); } else close(sc); } return 0; }
爲了方便處理,服務器端在接收到客戶端的請求後會fork一個新的進程來處理。函數fork出來的進程集成了父進程的屬性,淚如套接字描述符,在子進程和父進程中都各有一套。網絡
爲了防止誤操做,在父進程中關閉了客戶端的套接字描述符,在子進程中關閉了服務器端的套接字描述符。一個進程中套接字的關閉不會形成套接字的真正關閉,只有當全部使用這些套接字的進程都關閉該套接字描述符,linux內核才釋放它們。socket
2、客戶端代碼函數
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8888 #define LENGTH 1024 void process_conn_client(int s) { int size = 0; char buffer[LENGTH]; for(;;){ size = read(0, buffer, LENGTH); if(size > 0){ write(s, buffer, size); size = read(s, buffer, LENGTH); write(1, buffer, size); } } } int main(int argc, char**argv) { int s; struct sockaddr_in server_addr; int err; s = socket(AF_INET, SOCK_STREAM, 0); if(s < 0){ printf("socket error\n"); return -1; } bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(PORT); connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); process_conn_client(s); close(s); return 0; }
下面將結合該例子與網絡協議棧源碼學習以下問題:學習
一、socket 本質spa
二、socket 數據發送機制code
三、socket 數據接收機制server