生活随笔
收集整理的這篇文章主要介紹了
MSG_PEEK标志
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
https://blog.csdn.net/aspnet_lyc/article/details/28937229
MSG_PEEK標(biāo)志可以用來讀取套接字接收隊列中可讀的數(shù)據(jù),一些情況會用到它,比如為了避免不阻塞而先檢查套接字接收隊列中可讀的數(shù)據(jù)長度,再采取相應(yīng)操作。
當(dāng)然,不阻塞也可采取其他的方法,例如非阻塞式I/O。
MSG_PEEK標(biāo)志會將套接字接收隊列中的可讀的數(shù)據(jù)拷貝到緩沖區(qū),但不會使套接子接收隊列中的數(shù)據(jù)減少,常見的是:例如調(diào)用recv或read后,導(dǎo)致套接字接收隊列中的數(shù)據(jù)被讀取后而減少,而指定了MSG_PEEK標(biāo)志,可通過返回值獲得可讀數(shù)據(jù)長度,并且不會減少套接字接收緩沖區(qū)中的數(shù)據(jù),所以可以供程序的其他部分繼續(xù)讀取。
注意:假設(shè)指定MSG_PEEK標(biāo)志,以一個長度為1024字節(jié)的緩沖區(qū)對一個TCP套接字調(diào)用recv,返回100,如果再次調(diào)用recv,返回值可能超過100,因為兩次調(diào)用之間可能有新的數(shù)據(jù)到達,導(dǎo)致長度增加。
下面是一個客戶-服務(wù)程序,客戶向服務(wù)端發(fā)送"Hello Server",服務(wù)器端指定MSG_PEEK標(biāo)志獲得可讀的長度后,并再次調(diào)用不指定MSG_PEEK的recv讀取,兩次讀取都能得到數(shù)據(jù),因為指定了MSG_PEEK后套接字接收緩沖區(qū)不會減少。
net.h
#ifndef MY_NET_H #define MY_NET_H #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <arpa/inet.h> #include <unistd.h> #include <time.h> #include <string.h> #include <sys/select.h> #include <sys/time.h> #include <errno.h>#include <signal.h>#include <iostream>#include <sys/stat.h>#include <fcntl.h> using namespace std; #define SA struct sockaddr int Init_sockaddr(struct sockaddr_in *stru, const int protoc, const char *addr,const unsigned int port){ if (stru == NULL || addr == NULL) return -1; if (inet_addr(addr) == INADDR_NONE) return -1; if (port > 65535) return -1; bzero((void*)stru, sizeof(*stru));stru->sin_family = protoc;(stru->sin_addr).s_addr = inet_addr(addr);stru->sin_port = htons(port); return 0;} int Tcp_connect(const char *addr,const unsigned int port){ int sockfd; struct sockaddr_in saddr; if((Init_sockaddr(&saddr, AF_INET, addr, port)) == -1) return -1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1; if(connect(sockfd, (SA*)&saddr, sizeof(saddr)) == -1){close(sockfd); return -1;} return sockfd;} int Tcp_listen(const char *addr,const unsigned int port,const int backlog){ int sockfd; struct sockaddr_in saddr; if (addr == NULL) return -1; if (strcmp(addr, "INADDR_ANY") == 0){ if (port > 65535) return -1; if (backlog < 0) return -1; bzero((void*)&saddr, sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = htonl(INADDR_ANY);saddr.sin_port = htons(port);} else{ if (Init_sockaddr(&saddr, AF_INET, addr, port) == -1) return -1;} if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1; if (bind(sockfd, (SA*)&saddr, sizeof(saddr)) == -1){close(sockfd); return -1;} if (listen(sockfd, backlog) == -1){close(sockfd); return -1;} return sockfd;} #endif
客戶程序
#include <iostream>#include "net.h"using namespace std; int main(){ int sockfd;sockfd = Tcp_connect("127.0.0.1", 9999); if (sockfd == -1){ cout << "Tcp_connect error" << endl; return -1;} char send_buf[] = "Hello Server"; char *p = send_buf; int r; int count = 0; while (1){r = write(sockfd, p, strlen(p)); if (r == -1){perror("write error"); return -1;}p += r;count += r; if (count == strlen(send_buf)) break;} while(1); return 0;}
服務(wù)器程序
#include <iostream>#include <unistd.h>#include "net.h"using namespace std; int main(){ int sockfd;sockfd = Tcp_listen("INADDR_ANY", 9999, 5); if (sockfd == -1){ cout << "Tcp_listen error" << endl; return -1;} int clifd; if ((clifd = accept(sockfd, NULL, NULL)) == -1){ cout << "accept error" << endl; return -1;} cout << "有新連接" << endl; sleep(5); char buf[100]; int r; r = recv(clifd, buf, sizeof(buf), MSG_PEEK); cout << "接收隊列中可讀的數(shù)據(jù)長度:" << r << endl; cout << "buf:" << buf << endl;r = recv(clifd, buf, sizeof(buf), 0); cout << "讀取長度:" << r << endl; cout << "buf:" << buf << endl; return 0;}
執(zhí)行結(jié)果
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的MSG_PEEK标志的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。