Home > Software engineering >  How to receive CHUNK's of data from recv() in BSD Sockets in C programming?
How to receive CHUNK's of data from recv() in BSD Sockets in C programming?

Time:10-05

I have implemented a websocket client library in C using socket. It was working properly with many websocket servers. But when I try to connect with one of my customer server, the websocket message was comes in many chunks of data. For all other servers, when I use recv() it will receive one whole websocket frame completely but this particular server will send that one websocket frame in 2 TCP packets so I have to again use recv() to get the remaining websocket frame. Then I tried to check this server with some websocket client tools and it was working fine. I need to know the logic, to implement the recv() for this and how to concatenate and figure when the websocket frame was completely received to parse the data? Somebody help me with this please.

while(1){
  ws_recv_ret = recv(*ws_sock, ws_recv, 1024, 0);
  ws_parser_execute(&ws_frame_parser1, ws_recv);
}

CodePudding user response:

TCP recv is allowed to receive any number of bytes up to the maximum number you ask for. The "packets" are totally unpredictable and you must not rely on them at all whatsoever.

How do you tell the size of a websocket frame? You use the websocket protocol, of course. The websocket header tells you how many bytes there are in the websocket frame. You need to keep calling recv until you have all the bytes.

If you recv too many bytes then you need to save the extra ones and use them for the next frame. If you carefully calculate how many bytes to receive at once, then you'll never receive too many, but many programs do try to receive as many bytes as possible, because that is more efficient, and so they need to deal with extra bytes.

And of course, because the "packets" are totally unpredictable the "packet" could end in the middle of the header. So you need to keep calling recv until you have the whole header, and then you know how many bytes there are, and then you need to keep calling recv until you have all the bytes.

Slightly more annoyingly, websocket headers can have different sizes. So you need to keep calling recv until you know how big the header is, then you need to keep calling recv until you have the whole header, and then you need to keep calling recv until you have all the bytes.

CodePudding user response:

I have used MSG_DONTWAIT flag in recv and run it in a loop and append new data to the buffer. After that the recv throws -1 with errno EAGAIN then I break the loop and parse the websocket data. And thanks @user253751 for the explanation, it helps to clear some doubt which arose in my mind about the implementation. The below is the code snippet I used in my library.

ws_recv_totalSize = 0;
ws_recv_ret = 0;
while(1){
  ws_recv_totalSize  = ws_recv_ret;
  ws_recv_ret = recv(*ws_sock, ws_recv   ws_recv_totalSize, MAX_BUFFER- ws_recv_totalSize, MSG_DONTWAIT);
      
  if(ws_recv_ret <= 0)
    break;
}
  • Related