天天看點

SO_RCVTIMEO ,  MSG_WAITALL

 test SO_RCVTIMEO and MSG_WAITALL 

1.首先兩者都運用于阻塞的情景下,對nonblock的fd不起作用。

2.SO_RCVTIMEO, socket選項,作為getsockopt, setsockopt的參數。見下 figure1. 

SO_RCVTIMEO選項可以指定阻塞調用的逾時時長,SO_RCVTIMEO的影響的函數read, readv, recv, recvfrom, recvmsg.

3.MSG_WAITALL, recv調用的參數,

MSG_WAITALL
              On  SOCK_STREAM  sockets  this  requests that the function block
              until the full amount of data can be returned. The function  may
              return  the  smaller  amount of data if the socket is a message-
              based socket, if a signal is caught, if the connection is termi‐
              nated,  if MSG_PEEK was specified, or if an error is pending for
              the socket.



ps:
recv(sockfd, buff, buff_size, MSG_WAITALL),
在正常情況下recv 是會等待直到讀取到buff_size 長度的資料,但是這裡的WAITALL 也隻是盡量讀全,在有中斷的情況下recv 還是可能會被打斷,造成沒有讀完指定的buff_size的長度。

是以即使是采用recv + WAITALL 參數還是要考慮是否需要循環讀取的問題,在實驗中對于多數情況下recv (使用了MSG_WAITALL)還是可以讀完buff_size,是以相應的性能會比直接read 進行循環讀要好一些。

閱讀原文.->   https://blog.csdn.net/kai8wei/article/details/77479240
           

figure1.

SO_RCVTIMEO ,  MSG_WAITALL
//test.......
//recv(s_sock, buffer, SIZE_BUFFER - 1, MSG_WAITALL)
//setsockopt(s_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))



#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<string.h>
#include<errno.h>
#include<arpa/inet.h>
#include<fcntl.h>


#define PORT 32767
#define NUM_LISTEN 20
#define SIZE_BUFFER 1024



int main()
{
        pid_t pid = 0;
        int s_sock = 0;
        sockaddr_in s_addr;
        //create socket.
        s_sock = socket(AF_INET, SOCK_STREAM, 0);
        if(-1 == s_sock){
                std::cout<<"call socket faild."<<std::endl;
                return -1;
        }

        //bind socket.
        bzero(&s_addr, sizeof(s_addr));
        s_addr.sin_family = AF_INET;
        s_addr.sin_addr.s_addr = inet_addr("118.25.216.246");
        s_addr.sin_port = htons(PORT);


        //setsockopt SO_RCVTIMEO
        timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 0;


        if(-1 == setsockopt(s_sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))){
                std::cout<<"call setsockopt faild."<<std::endl;
                return -1;
        }

        std::cout<<"set SO_RCVTIMEO."<<std::endl;
        int iRet = connect(s_sock, (sockaddr*)&s_addr, sizeof(s_addr));
        if(-1 == iRet){//error occured.
                std::cout<<"call connect faild. error code: "<<errno<<std::endl;
                std::cout<<"error descriptions: \n\t"<<strerror(errno)<<std::endl;
                return iRet;
        }

        //send msg.
        //char* msg = "hello";
        //write(s_sock, msg, strlen(msg));


        //set socket nonblock.
//      int flags = fcntl(s_sock, F_GETFL, 0);
//      flags |= O_NONBLOCK;
//      fcntl(s_sock, F_SETFL, flags);

        //recv msg.
        char buffer[SIZE_BUFFER];
        bzero(buffer, SIZE_BUFFER);

        std::cout<<"ready read."<<std::endl;

        int n = 0;
        while(true)
        if(0 < (n = recv(s_sock, buffer, SIZE_BUFFER - 1, MSG_WAITALL))){//read buffer.
                std::cout<<buffer<<std::endl;
                return -1;
        }
        else
                std::cout<<"continue"<<std::endl;

        return 0;
}


           

繼續閱讀