一塊兒來:
誒,不要着急,咱們先來介紹一些網絡程序的主要執行過程,主要是便於你們更好的理解下面的程序實例哦 :
1)系統啓動服務器執行。服務器完成一些初始化操做,而後進入睡眠狀態,等待客戶機請求。
2)在網絡的某臺機器上,用戶執行客戶機程序
3)客戶機進行與服務器進程創建一條鏈接
4)鏈接創建後,客戶機經過網路向服務器發出請求,請求某種服務。
5)服務器接收到客戶機的請求後,根據客戶機請求的內容進行相應的處理,而後將處理結果返回。
6)服務器斷開與客戶機的鏈接,繼續睡眠,等待其餘客戶機的請求。
如今介紹一個實例
功能:實現簡單的服務器-客戶機編程,客戶機發送鏈接請求後接受到鏈接成功信息。
代碼包括兩部分,服務器部分(service.c)和客戶機部分(client.c)
1 /*service.c*/ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <errno.h> 5 #include <string.h> 6 #include <sys/types.h> 7 #include <netinet/in.h> 8 #include <sys/socket.h> 9 #include <sys/wait.h> 10 #define MYPORT 3490 /*開放的端口號*/ 11 #define BACKLOG 5 /*指定套接字能夠接受的最大未接受客戶機請求的數目*/ 12 main() 13 { 14 int sockfd,new_fd; 15 struct sockaddr_in srvaddr; 16 struct sockaddr_in cliaddr; 17 int sin_size; 18 /*建立套接字描述符*/ 19 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) 20 { 21 perror("socket error"); 22 exit(1); 23 } 24 bzero(&srvaddr,sizeof(srvaddr)); 25 /*用本身的ip地址和端口信息填充一個internet套接字地址結構*/ 26 srvaddr.sin_family=AF_INET; 27 srvaddr.sin_port=htons(MYPORT); 28 /*函數bind將服務器的地址和套接字幫定在一塊兒*/ 29 if(bind(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))==-1) 30 { 31 perror("bind error"); 32 exit(1); 33 } 34 /*listen函數告訴內核,這個套接字能夠接受來自客戶機的請求*/ 35 if(listen(sockfd,BACKLOG)==-1) 36 { 37 perror("listen error"); 38 exit(1); 39 } 40 /*處理客戶機的請求,調用函數accept來得到一個客戶機的鏈接*/ 41 for(;;) 42 { 43 sin_size=sizeof(struct sockaddr_in); 44 if((new_fd=accept(sockfd,(struct sockaddr *)&cliaddr,&sin_size))==-1) 45 { 46 perror("accept error"); 47 continue; 48 } 49 printf("server: got connection from %s \n",inet_ntoa(cliaddr.sin_addr)); 50 /*向客戶起寫數據*/ 51 if(write(new_fd,"Hello,Network!\n",14)==-1) 52 perror("write error!"); 53 close(new_fd); 54 } 55 close(sockfd); 56 }
下面爲client:
1 /*client.c*/ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <errno.h> 5 #include <string.h> 6 #include <netdb.h> 7 #include <sys/types.h> 8 #include <netinet/in.h> 9 #include <sys/socket.h> 10 #define PORT 3490 11 #define MAXDATASIZE 5000 12 int main(int argc,char **argv) 13 { 14 int sockfd,nbytes; 15 char buf[1024]; 16 struct hostent *he; 17 struct sockaddr_in srvaddr; 18 if(argc!=2) 19 { 20 perror("Usage:client hostname\n"); 21 exit(1); 22 } 23 /*函數gethostbyname得到指定域名地址所對應的ip地址*/ 24 if((he=gethostbyname(argv[1]))==NULL) 25 { 26 perror("gethostbyname"); 27 exit(1); 28 } 29 /*建立套接字,返回套接字描述符*/ 30 if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) 31 { 32 perror("create socket error"); 33 exit(1); 34 } 35 bzero(&srvaddr,sizeof(srvaddr)); 36 /*用得到的遠程服務器進程的ip地址和端口號來填充一個internet套接字地址結構*/ 37 srvaddr.sin_family=AF_INET; 38 srvaddr.sin_port=htons(PORT); 39 srvaddr.sin_addr=*((struct in_addr *)he->h_addr); 40 /*用connect於這個遠程服務器創建一個internet鏈接*/ 41 if(connect(sockfd,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr))==-1) 42 { 43 perror("connect error"); 44 exit(1); 45 } 46 /*調用read函數讀取服務器write過來的信息*/ 47 if((nbytes=read(sockfd,buf,MAXDATASIZE))==-1) 48 { 49 perror("read error"); 50 exit(1); 51 } 52 buf[nbytes]='\0'; 53 printf("read: %s",buf); 54 close(sockfd); 55 }
下面咱們來編譯執行看看效果哦
編譯:
#gcc -o service service.c
#gcc -o client client.c
修改執行權限
#chmod 770 service
#chmod 770 client
執行
現執行服務器端哦
#./service
另開一個命令行窗口,鏈接服務器的3490端口
#./client localhost
呵呵,看到效果了吧
服務器端:
|
客戶端
|