How to make recv have a little temper?

Hello, I'm brother Tao.

Today, let's talk about the recv function in TCP network programming. As we know, recv is a blocking function. When no data is received, it will wait for the data foolishly.

So, how to make the recv function have a little temper instead of waiting foolishly? The select function can be on top. Next, let's practice and deepen our understanding of network programming.

Hand painted by Taoge

I Grumpy recv function

When the recv function has no temper, it will only wait foolishly until the end of time. Let's look at the server program and let the server run first.

We can see that when a TCP connection is established, the server deliberately waits 3 seconds to send data. Can the client afford to wait? Are you patient?

#include <stdio.h>
#include <winsock2. h> / / Winsock interface
#pragma comment(lib, "ws2_32.lib") // winsock implementation
 
int main()
{
  WORD wVersionRequested;  // Double byte, version of winsock Library
  WSADATA wsaData;         // Information about winsock library version
  
  wVersionRequested = MAKEWORD(1, 1); // 0x0101: 257
  
  // Load the winsock library and determine the winsock version, and the system will fill the data into wsaData
  WSAStartup( wVersionRequested, &wsaData );
 
  // AF_INET means using TCP/IP protocol family
  // SOCK_STREAM means TCP protocol is adopted
  // 0 is the usual default
  unsigned int sockSrv = socket(AF_INET, SOCK_STREAM, 0);
 
  SOCKADDR_IN addrSrv;
 
  addrSrv.sin_family = AF_INET; // TCP/IP protocol family
  addrSrv.sin_addr.S_un.S_addr = inet_addr("0.0.0.0"); 
  addrSrv.sin_port = htons(8888); // Port corresponding to socket
 
  // Bind the socket to an IP and port (IP identifies the host and port identifies the communication process)
  bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
 
  listen(sockSrv, 5);
 
  SOCKADDR_IN addrClient;
  int len = sizeof(SOCKADDR);
  
  while(1)
  {
    unsigned int sockConn = accept(sockSrv,(SOCKADDR*)&addrClient, &len);
    printf("accept is returned\n");
 
    Sleep(3000);
    char sendBuf[100] = "hello";
    send(sockConn, sendBuf, strlen(sendBuf) + 1, 0); // Send data to the client, and the last parameter is generally set to 0
    //closesocket(sockConn);  
  }
 
  closesocket(sockSrv);
  WSACleanup();
  
  return 0;
}

Next, we look at the client program and let the client run. Running the client program, you can find that although the server deliberately delayed for 3 seconds, the client has unlimited patience and can still receive data.

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
 
int main()
{
  WORD wVersionRequested;
  WSADATA wsaData;
  wVersionRequested = MAKEWORD(1, 1);
  
  WSAStartup( wVersionRequested, &wsaData );
 
  SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
 
  SOCKADDR_IN addrSrv;
  addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
  addrSrv.sin_family = AF_INET;
  addrSrv.sin_port = htons(8888);
 
  int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
  printf("connect ret is %d\n", ret);
 
      
  char recvBuf[200] = "x";
  ret = recv(sockClient, recvBuf, 100, 0);
  if(0 > ret)
  {
    printf("recv error");
    return -3;
  }
 
  if(0 == ret)
  {
    printf("recv ret is %d\n", ret);
    return -4;
  }
  
  printf("%s\n", recvBuf);
 
  while(1);
 
  closesocket(sockClient);
  WSACleanup();
 
  return 0;
}

II recv function with temper

The recv function should be a little grumpy. After waiting for 4 seconds, I won't wait until you come. How? The timeout feature of the select function can be used. The client program is as follows:

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
 
int main()
{
  WORD wVersionRequested;
  WSADATA wsaData;
  wVersionRequested = MAKEWORD(1, 1);
  
  WSAStartup( wVersionRequested, &wsaData );
 
  SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
 
  SOCKADDR_IN addrSrv;
  addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
  addrSrv.sin_family = AF_INET;
  addrSrv.sin_port = htons(8888);
 
  int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
  printf("connect ret is %d\n", ret);
  
  fd_set rfds;
  struct timeval timeout = {4, 0};
 
  FD_ZERO(&rfds); 
  FD_SET(sockClient, &rfds);
  ret = select(-1, &rfds, NULL, NULL, &timeout);
  printf("select ret is %d\n",ret);
  if(0 > ret)
  {
    printf("select error\n");
    return -1;
  }
   
  if(0 == ret)
  {
    printf("time out\n");
    return -2;
  }
    
  if(FD_ISSET(sockClient, &rfds))
  {
    char recvBuf[200] = "x";
    ret = recv(sockClient, recvBuf, 100, 0);
    if(0 > ret)
    {
      printf("recv error");
      return -3;
    }
 
    if(0 == ret)
    {
      printf("recv ret is %d, buf is %s\n", ret, recvBuf);
      return -4;
    }
    
    printf("%s\n", recvBuf);
    }
 
  while(1);
  closesocket(sockClient);
  WSACleanup();
 
  return 0;
}

The client's patience is only 4 seconds. The client says: the server, you TM. After I establish a TCP relationship with you, if you don't send data within 4 seconds, I'll ignore you.

Running the program, you can see that the client can receive the data, because the server obediently transmitted the data in 4 seconds, which did not reach the 4-second limit that the client tolerated

What happens if the client's endurance value is changed to 2 seconds? After testing, the client waited for 2 seconds and waited. Naturally, it didn't receive the data. It's grumpy enough.

In the actual network programming, almost all network related operations need to set timeout, such as connection timeout, sending timeout and receiving timeout, which are everywhere.

When learning computer network and network programming, many people have prepared many eight part essays for the written interview, such as three handshakes and four waves. These preparations are necessary.

However, these are not enough. Computer network is a highly practical subject. I personally suggest writing more programs, debugging more, capturing more packages, and then analyzing it according to the theory.

Keywords: network server TCP/IP

Added by QuietWhistler on Mon, 07 Mar 2022 18:11:56 +0200