How to Receive Full Data with recv() Socket function in C on Linux – Code Example

By | August 11, 2020

Socket function - recv()

If you are writing a network application using sockets in C that communicates with a remote server and fetches data, then you must be aware of the recv function that is used to receive data.

The recv function can only receive a specified number of bytes in the response. If the response has less content than the specified byte size then its okay.

But if the response is larger than the specified number of bytes then only the initial chunk is received and the rest is lost.

This is the typical problem with the recv function. Lets take a look at an example to understand what is happening.

Code example

The recv function is used to receive data on a socket.
For example here is the code to fetch the home page of

	Simple TCP client to fetch a web page

#include<string.h>	//strlen
#include<arpa/inet.h>	//inet_addr

int main(int argc , char *argv[])
	int socket_desc;
	struct sockaddr_in server;
	char *message , server_reply[6000];
	//Create socket
	socket_desc = socket(AF_INET , SOCK_STREAM , 0);
	if (socket_desc == -1)
		printf("Could not create socket");
	//ip address of (get by doing a ping at terminal)
	server.sin_addr.s_addr = inet_addr("");
	server.sin_family = AF_INET;
	server.sin_port = htons( 80 );

	//Connect to remote server
	if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
		puts("connect error");
		return 1;
	//Send some data
	message = "GET /?st=1 HTTP/1.1\r\nHost:\r\n\r\n";
	if( send(socket_desc , message , strlen(message) , 0) < 0)
		puts("Send failed");
		return 1;
	puts("Data Send\n");
	//Receive a reply from the server
	if( recv(socket_desc, server_reply , 6000 , 0) < 0)
		puts("recv failed");
	puts("Reply received\n");
	return 0;

The output might be something like this

$ gcc simple_client.c && ./a.out
Data Send
Reply received
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Set-Cookie: MC1=V=3&GUID=fd76ac7b61c9436f9a414441d186becd;; expires=Mon, 08-Sep-2014 09:58:09 GMT; path=/
Set-Cookie: MC1=V=3&GUID=fd76ac7b61c9436f9a414441d186becd;; expires=Mon, 08-Sep-2014 09:58:09 GMT; path=/
Set-Cookie: mh=MSFT;; expires=Mon, 08-Sep-2014 09:58:09 GMT; path=/
Set-Cookie: CULTURE=EN-US;; expires=Sat, 15-Sep-2012 09:58:09 GMT; path=/
Set-Cookie: CC=IN;; expires=Mon, 08-Sep-2014 09:58:09 GMT; path=/
Set-Cookie: _FS=NU=1;; path=/
Set-Cookie: _SS=SID=842BD72E52E84B36A38CD2350EB80138;; path=/
Set-Cookie: SRCHD=D=2465878&MS=2465878&AF=NOFORM; expires=Mon, 08-Sep-2014 09:58:09 GMT;; path=/
Set-Cookie: SRCHUID=V=2&GUID=9ACA924189EA4BF28C133336D34D51EF; expires=Mon, 08-Sep-2014 09:58:09 GMT; path=/
Set-Cookie: SRCHUSR=AUTOREDIR=0&GEOVAR=&DOB=20120908; expires=Mon, 08-Sep-2014 09:58:09 GMT;; path=/
errorCodeCount: [0:0]
S: CO3SCH010130401
Edge-control: no-store
Date: Sat, 08 Sep 2012 09:58:09 GMT
Content-Length: 111667
<!DOCTYPE html><html xml:lang="en-us" lang="en-us" dir="ltr" xmlns=""><head><meta http-equiv=

The problem with the output is that it is incomplete. We already used a large sized buffer of 6000 characters to receive the reply.

There cause of this problem is that we do not know the exact size of the response beforehand.

We might try to do any of these :

1. Use a very large buffer - But all data does not come in at once. The response comes as several TCP packets. So the recv function would return after receiving even partial data.

2. Making recv function wait till full size is received - But we do not know the full size.

Receive in multiple chunks - The Solution

A simple solution might look like this

int receive_basic(int s)
	int size_recv , total_size= 0;
	char chunk[CHUNK_SIZE];
		memset(chunk ,0 , CHUNK_SIZE);	//clear the variable
		if((size_recv =  recv(s , chunk , CHUNK_SIZE , 0) ) < 0)
			total_size += size_recv;
			printf("%s" , chunk);
	return total_size;

If the CHUNK_SIZE is relatively small compared to the total size of the response then it will work but partially.
Lets say the CHUNK_SIZE = 512 and data is much larger. Then the recv function would receive data in a fashion similar to this

CHUNK_SIZE + CHUNK_SIZE + CHUNK_SIZE ..... + something less than CHUNK_SIZE.

The last call would be returning an amount of data that is smaller than the chunk size (unless the whole response size is a multiple of the CHUNK_SIZE).

Now in the last call to recv, it would block till it gets CHUNK_SIZE amount of data or a default timeout occurs which can be from 30 seconds to 1 minute. This can be too much of waiting for an application.

An alternative strategy would be to receive without waiting and with a specific maximum timeout. Here are the steps ...

1. Try to receive some data, lets say 512 bytes. If nothing is received till a certain timeout then stop.
2. Go to step 1.

Final Code

The recv_timeout function receives data on a socket with a given maximum timeout. The above program should fetch the full html content of till the closing html tag.

Data is received in chunks of size 512 bytes. This can be set to a different value like 1024 or 2000 or anything.

Another important change is that the socket is set in non blocking mode. When the socket is in non-blocking mode, then recv would not block and return immediately. If data is there it would return with the data otherwise with an error.

In the above example the socket can be kept blocking. Then the recv function must use the flag MSG_DONTWAIT

Both techniques should produce identical results.


This technique of waiting for some timeout may not be the most efficient or reliable technique to ensure that full data has been received.

The most reliable approach would be to have some sort of indicator that confirms completion of transfer.

The reply can for example have and "end marker" or the total response size mentioned in it somewhere so that the receiving application can judge it better.

If you have any feedback or questions, let us know in the comments below.

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

16 thoughts on “How to Receive Full Data with recv() Socket function in C on Linux – Code Example

  1. Leon Chang

    Thanks for a very useful article. I tried your code and found that a modified receive_basic() code can do away with the recv_timeout(int s , int timeout) function. Instead of making the socket nonblocking with fcntl(), one can use setsockopt() to set a desired timeout value in receive_basic(). For example, the below receive_basic(int s_fd) would wait for 1.5 seconds to time out and be able to receive all the data — Received 48046 bytes from

    #define CHUNK_SIZE 2048
    #define TO_SEC 1
    #define TO_USEC 50000

    int receive_basic(int s_fd) // Block on recv
    int rcvBytes, loopRcvd = 0, totalRcvd = 0;
    char chunk[CHUNK_SIZE];

    struct timeval tv = {TO_SEC, TO_USEC};
    setsockopt(s_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    memset(chunk, 0, CHUNK_SIZE);
    if ((rcvBytes = recv(s_fd, chunk, sizeof(chunk), 0)) >\n%s\n”, rcvBytes, loopRcvd, chunk);

    printf(“Exiting receive_basic(s_fd %d) with loopRcvd %d\n\n”, s_fd, loopRcvd);
    return totalRcvd;

    One should set the timeout value at least longer than the expected arrival time of the first chunk message, else the loop may break prematurely with 0 received bytes.

  2. Tahir Abulubbad

    put the recv system call in a loop instead of if statement (repeat until it returns 0). it’ll then receive the full data. to end the connection, simply add the following header to your http message:
    Connection: close

    1. Kelly Corrigan

      Does this assume that the remote server closes the socket as soon as it’s finished sending the message? As I understand, recv() only returns 0 if the socket has been closed. So this method wouldn’t work if you want to keep the connection open for a reply, right?

  3. David Peterson Harvey

    If you get error messages with this code on your Linux machine, look for the following problems.

    1. Don’t forget to “#include ” for the gettimeofday() function.
    2. Get rid of the declaration for “server_reply[2000]” because it is unused and will generate a warning.

  4. David Peterson Harvey

    Very good article for someone (like me) who is just now learning about sockets in C. Thanks very much for posting this article! I’ve been going nuts trying to figure out how to do this. :-)

    Is there any way to request an end marker or total response size from the server or would this have to be coded into the server-side program?

    1. Silver Moon

      There is no direct way of fetching the total response size. It has to be coded in the server and client program.

      1. For example 2 consecutive newlines can indicate the end of data. So this logic has to be coded in both the server and the client. The server appends 2 newlines to the total response, and the client upon detecting such a pattern closes the connection and marks transfer complete for the application.

      2. Another way is to send the total size before sending the actual response. For example server sends like this


      So first the total size is mentioned and then after 2 newlines the actual response follows, so the client has to deal with this, either wait till 1024 bytes of data in the response part is received. For example http response send by http servers has a “content-length” value in its header which tells the total size of the response.

      Both the techniques can be developed further to ensure reliable transfer of full data.

      1. David Peterson Harvey

        Still playing around with your code, making changes to see how things work and what I can do with it. Playing around with headers and portions of the code to get a better feel for how it works.

        Thanks again for sharing your knowledge!

      2. Zander

        year but this is not at tutorial in how to recive a known data size.

        what if you want to recive from a external server, that dosent send the size of the packet?

        1. Silver Moon

          if the server does not send the size of the packet, then the program has to decide this itself whether the transfer has completed or not.
          For example if the socket connection closes or no data received for a large timeout.

          Simply put, its not possible to know if the transfer completed successfully or not.

    1. Suraj A

      HTTPS might not work since you are expected to have a valid certificate or credentials. You can try working with an authenticity manager..

Leave a Reply

Your email address will not be published. Required fields are marked *