使用socket创建服务器进程和客户端进程
生活随笔
收集整理的這篇文章主要介紹了
使用socket创建服务器进程和客户端进程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
TCP客戶端和服務器創建流程在上篇博文中已經說明:
TCP客戶端服務器模型創建流程
服務器進程
#include <netdb.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <signal.h> #include <time.h>//測試方法,運行程序,并指定端口號8888 //在另一個終端上使用 // telnet 127.0.0.1 8888進行連接 //127.0.0.1是沒有連接網絡時使用的本地回環ip地址//使用瀏覽器測試,需要使用使用http協議進行,在瀏覽器中輸入http://IP.8888 即可訪問(本機測試)/*聲明自定義函數*/ void sig_handler(int signo); void out_addr(struct sockaddr_in *clientaddr); void do_service(int fd); int sockfd;int main(int argc, char * argv[]) {if(argc < 2){printf("usage: %s #port\n",argv[0]);exit(1);}if(signal(SIGINT, sig_handler) == SIG_ERR) //開始捕捉信號 SIGINT{perror("signal sigint error!");exit(1);}/*步驟1創建socket*AF_INET IPV4*SOCK_STREAM 采用tcp協議*0 采用上面設置的協議類型*/sockfd = socket(AF_INET, SOCK_STREAM, 0); //使用默認協議if(sockfd < 0){perror("socket error!");exit(1);}/**步驟2,:調用bind函數將socket和地址(包括 IP,port)進行綁定**/struct sockaddr_in serveraddr; //聲明專用地址,需要的時候再轉換為通用地址memset(&serveraddr, 0, sizeof(serveraddr));//往地址填入ip、port、intnernet地址族類型serveraddr.sin_family = AF_INET; //IPV4serveraddr.sin_port = htons(atoi(argv[1])); //填入端口 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(sockfd, (struct sockaddr *) &serveraddr,sizeof(serveraddr)) < 0){perror("bind error!");exit(1);}/* *步驟3:調用listen函數啟動端口監聽*通知系統去接受來自客戶端的連接請求*listen 的第二個參數10是請求隊列長度,將接收到的客戶端連接請求放到對應的隊列當中*/if(listen(sockfd, 10) < 0) //10監聽的隊列的上限{perror("listen error!");exit(1);}/**步驟4:調用accept函數,從隊列中獲得* 一個客戶端請求連接,并返回新的sock文件描述符fd,* 因為listen能夠監聽好多的連接請求,* 使用accept獲得一個連接使用* 若是accept沒有獲得客戶端連接,會進行阻塞,直到獲得客戶端連接*/struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);while(1){//使用循環就能夠在斷開與一個客戶端連接之后,在連接下一個客戶端連接int fd = accept(sockfd, (struct sockaddr*) &clientaddr,&clientaddr_len);if(fd < 0){perror("accept error!");continue;}/**步驟5: 調用IO函數(read/write)和連接的客戶端進行雙向通信**/out_addr(&clientaddr);do_service(fd);/*步驟6:關閉socket*/close(fd);}return 0; }void sig_handler(int signo) {if(signo == SIGINT){printf("server close\n");/*步驟6:關閉socket*/close(sockfd);exit(1);}}void out_addr(struct sockaddr_in *clientaddr) {/*將端口網絡字節序轉換為主機字節序 */ /*port是short類型數據*/int port = ntohs(clientaddr->sin_port);char ip[16];memset(ip, 0, sizeof(ip));/*將ip地址從網絡地址轉換為點分十進制*//*需要注意的地方#include <arpa/inet.h>const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);在函數中 const void *src說明第二個參數是指針類型的數據,但是當傳入clientaddr->sin_addr.s_addr == (*clientaddr).sin_addr.s_addr就不在是一個指針類型數據因此需要使用&將其取址之后在傳入。*/inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip));printf("client: %s(%d) connected\n",ip, port); }void do_service(int fd) {long t = time(0);char *s = ctime(&t);size_t size = strlen(s)*sizeof(char);/*將服務器端獲取的系統時間寫回到客戶端*/if(write(fd, s, size) != size){perror("write error!");}}客戶端進程
#include <netdb.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <signal.h> #include <time.h>int main(int argc, char * argv[]) {if(argc < 3){printf("usage:%s ip port\n",argv[0]);exit(1);}/*步驟1:創建socket*/int sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket error!");exit(1);}/*往serveraddr中填入ip,port和地址族類型(ipv4)*/struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));/*將字符串ip地址轉換為網絡字節序填入 serveraddr中*/inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);/**步驟2: 客戶端調用connect函數連接到服務器端*/if(connect(sockfd, (struct sockaddr *)&serveraddr,sizeof(serveraddr)) < 0){perror("connect error!");exit(1);}/*步驟3:調用IO函數,read和write和服務器進行雙向通信*/char buffer[1024];memset(buffer, 0, sizeof(buffer));size_t size;if((size = read(sockfd, buffer, sizeof(buffer))) < 0){perror("read error!");exit(1);}if(write(STDOUT_FILENO, buffer, size) != size){perror("write error!");exit(1);}/*步驟4:關閉socket套接字*/close(sockfd);return 0; }總結
以上是生活随笔為你收集整理的使用socket创建服务器进程和客户端进程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 作者: 李国杰,中国工程院院士。现任中
- 下一篇: 作者:王建新(1969-),博士,中南大