生活随笔
收集整理的這篇文章主要介紹了
MSG_PEEK标志
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
https://blog.csdn.net/aspnet_lyc/article/details/28937229
MSG_PEEK標志可以用來讀取套接字接收隊列中可讀的數據,一些情況會用到它,比如為了避免不阻塞而先檢查套接字接收隊列中可讀的數據長度,再采取相應操作。
當然,不阻塞也可采取其他的方法,例如非阻塞式I/O。
MSG_PEEK標志會將套接字接收隊列中的可讀的數據拷貝到緩沖區,但不會使套接子接收隊列中的數據減少,常見的是:例如調用recv或read后,導致套接字接收隊列中的數據被讀取后而減少,而指定了MSG_PEEK標志,可通過返回值獲得可讀數據長度,并且不會減少套接字接收緩沖區中的數據,所以可以供程序的其他部分繼續讀取。
注意:假設指定MSG_PEEK標志,以一個長度為1024字節的緩沖區對一個TCP套接字調用recv,返回100,如果再次調用recv,返回值可能超過100,因為兩次調用之間可能有新的數據到達,導致長度增加。
下面是一個客戶-服務程序,客戶向服務端發送"Hello Server",服務器端指定MSG_PEEK標志獲得可讀的長度后,并再次調用不指定MSG_PEEK的recv讀取,兩次讀取都能得到數據,因為指定了MSG_PEEK后套接字接收緩沖區不會減少。
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;}
服務器程序
#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 << "接收隊列中可讀的數據長度:" << r << endl; cout << "buf:" << buf << endl;r = recv(clifd, buf, sizeof(buf), 0); cout << "讀取長度:" << r << endl; cout << "buf:" << buf << endl; return 0;}
執行結果
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的MSG_PEEK标志的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。