日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不恰当使用read会造成服务器阻塞

發(fā)布時(shí)間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不恰当使用read会造成服务器阻塞 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

可正常工作的tcp服務(wù)器:

#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>//測試方法,運(yùn)行程序,并指定端口號8888 //在另一個(gè)終端上使用 // telnet 127.0.0.1 8888進(jìn)行連接 //127.0.0.1是沒有連接網(wǎng)絡(luò)時(shí)使用的本地回環(huán)ip地址//使用瀏覽器測試,需要使用使用http協(xié)議進(jìn)行,在瀏覽器中輸入http://IP.8888 即可訪問(本機(jī)測試)/*聲明自定義函數(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) //開始捕捉信號 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ù)啟動端口監(jiān)聽*通知系統(tǒng)去接受來自客戶端的連接請求*listen 的第二個(gè)參數(shù)10是請求隊(duì)列長度,將接收到的客戶端連接請求放到對應(yīng)的隊(duì)列當(dāng)中*/if(listen(sockfd, 10) < 0) //10監(jiān)聽的隊(duì)列的上限{perror("listen error!");exit(1);}/**步驟4:調(diào)用accept函數(shù),從隊(duì)列中獲得* 一個(gè)客戶端請求連接,并返回新的sock文件描述符fd,* 因?yàn)閘isten能夠監(jiān)聽好多的連接請求,* 使用accept獲得一個(gè)連接使用* 若是accept沒有獲得客戶端連接,會進(jìn)行阻塞,直到獲得客戶端連接*/struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);while(1){//使用循環(huán)就能夠在斷開與一個(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說明第二個(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) {//獲取系統(tǒng)時(shí)間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!");}}

能正常工作的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>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; }

在do_service增加read之后,但是沒有在客戶端增加,發(fā)送數(shù)據(jù)函數(shù),會造成阻塞,如:

void do_service(int fd) {size_t len;char buff[20];if((len = read(fd, buff, 20)) < 0){perror("read error!");}//獲取系統(tǒng)時(shí)間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!");}}

?

更改之后的服務(wù)器:

#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>//測試方法,運(yùn)行程序,并指定端口號8888 //在另一個(gè)終端上使用 // telnet 127.0.0.1 8888進(jìn)行連接 //127.0.0.1是沒有連接網(wǎng)絡(luò)時(shí)使用的本地回環(huán)ip地址//使用瀏覽器測試,需要使用使用http協(xié)議進(jìn)行,在瀏覽器中輸入http://IP.8888 即可訪問(本機(jī)測試)/*聲明自定義函數(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) //開始捕捉信號 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ù)啟動端口監(jiān)聽*通知系統(tǒng)去接受來自客戶端的連接請求*listen 的第二個(gè)參數(shù)10是請求隊(duì)列長度,將接收到的客戶端連接請求放到對應(yīng)的隊(duì)列當(dāng)中*/if(listen(sockfd, 10) < 0) //10監(jiān)聽的隊(duì)列的上限{perror("listen error!");exit(1);}/**步驟4:調(diào)用accept函數(shù),從隊(duì)列中獲得* 一個(gè)客戶端請求連接,并返回新的sock文件描述符fd,* 因?yàn)閘isten能夠監(jiān)聽好多的連接請求,* 使用accept獲得一個(gè)連接使用* 若是accept沒有獲得客戶端連接,會進(jìn)行阻塞,直到獲得客戶端連接*/struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);while(1){//使用循環(huán)就能夠在斷開與一個(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說明第二個(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) {size_t len;char buff[20];if((len = read(fd, buff, 20)) < 0){perror("read error!");}//獲取系統(tǒng)時(shí)間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īng)過測試,服務(wù)器會阻塞到read函數(shù)的地方。

?

?

?

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的不恰当使用read会造成服务器阻塞的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。