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