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.****.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;
}