Receiving Data in Tcp

Receiving data in TCP

See Transmission Control Protocol:

TCP provides reliable, ordered delivery of a stream of bytes from a program on one computer to another program on another computer.

A "stream" means that there is no message boundary from the receiver's point of view. You could get one 1000 byte message or one thousand 1 byte messages depending on what's underneath and how often you call read/select.

Edit: Let me clarify from the application's point of view. No, TCP will not guarantee that the single read would give you all of the 1000 bytes (or 1MB or 1GB) packet the sender may have sent. Thus, a protocol above the TCP usually contains fixed length header with the total content length in it. For example you could always send 1 byte that indicates the total length of the content in bytes, which would support up to 255 bytes.

TCP - Sending and Receiving TCP/IP Data

Deja vu Will TCPStream read block until all data is received.

I realize it looks a little different but at the core they are very similar questions.

Don't make assumptions about packet sizes.

TCP C send data when not receiving data

First I will explain, why it does not work, then I will make a proposal for solutions. Basically you will find the answer in the man7.org > Linux > man-pages and for recv specifially here.

When the function "recv" is called, then it will not return, until data is available and can be read. This behavior of functions is called "blocking". Means, the current execution thread is blocked until data has been read.

So, calling the function

n = recv(sock, &buffer[0], buffer.size(), 0);

as you did, causes the trouble. You need also to check the return code. 0 means, connection closed, -1 means error and you must check errno for further information.

You can modify the socket to work in non-blocking mode with the function fnctl and the O_NONBLOCK flag, for the lifetime of the socket. You can also use the the flag MSG_DONTWAIT as 4th parameter (flags), to unblock the function on a per-function-call base.

In both cases, if no data is available, the functions returns a -1 and you need to check errno for EAGAIN or EWOULDBLOCK.

return value 0 indicates that the connection has been closed.

But from the architecture point of view, I would not recommend to use this approach. You could use multiple threads for receiving and sending data, or, using Linux, one of select, poll or similar functions. There is even a common design pattern for this. It is called "reactor", There are also related patterns like "Acceptor/Connector" and "Proactor"/"ACT" available. If you plan to write a more robust application, then you may consider those.

You will find an implementation of Acceptor, Connector, Reactor, Proactor, ACT here

Hope this helps

Problems receiving data over a TCP client socket

Print out the number of bytes received - it is likely to be zero, but confirm that.

It would be worth checking that you aren't getting an error - and therefore underflowing your buffer.

[Note: from here onwards is the work of Pax - thank you, and I've converted it to Community Wiki so I don't get rep points undeservedly.]

The following code will do this. Try it and report back on the results, please.

while (1) {
numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0);
buf[numbytes] = '\0';
printf("Count: %d, Error: %d, Received: %s\n", numbytes, errno, buf);
// more code to react goes here
}

After question edit:

Error number 111 is ECONNREFUSED - this is not a usual error code for recv(), but is more suited to the open-type call (open(), connect(), etc).

In any case, ECONNREFUSED is a problem at the server end, not the client - the server has purposefully refused to accept your incoming connection, so you will need to investigate that end of the link.

In order to test this, change your code so that it's connecting to www.microsoft.com on port 80, then send a couple of lines of any old rubbish. You should get back an error from their web server indicating a malformed HTTP request. This will prove there's no problem on your client end.

This is what I get back when I telnet www.microsoft.com 80 and type in hello followed by ENTER twice:

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 27 Nov 2008 01:45:09 GMT
Connection: close
Content-Length: 326

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Verb</h2>
<hr><p>HTTP Error 400. The request verb is invalid.</p>
</BODY></HTML>

You should see something similar.

Does TCP socket receive data in the same way as it was sent?

The recv and send networking calls might return fewer number of bytes sent/received than specified. You may want to have such function which receives exactly specified number of bytes.

#include <sys/types.h>
#include <sys/socket.h>

int readall(int s, char *buf, int *len)
{
int total = 0; // how many bytes we've read
int bytesleft = *len; // how many we have left to read
int n = -1;

while(total < *len) {
n = read(s, buf+total, bytesleft, 0);
if (n <= 0) { break; }
total += n;
bytesleft -= n;
}

*len = total; // return number actually read here

return (n<=0)?-1:0; // return -1 on failure, 0 on success
}

You can write a similar sendall function too. Then you use sendall to send first two bytes which specify message length for example, and then sendall the message. You do same on receiving side, first readall the message length, then the message.

How I can receive data for ever from TCP server

Read requires a Write on the other side of the connection

want to receive data forever

Then you have to send data forever. There's a for loop on the receiving end, but no looping on the sending end. The server writes its message once and closes the connection.

Server expects to get msg from client but client doesn't send it

    // conn.Write([]byte("Hello World"))

That's supposed to provide the msg value to the server

    _, err := conn.Read(buf)

So those two lines don't match.

Client expects a newline but server isn't sending one

fmt.Scanln expects to put each whitespace separated value into the corresponding argument. It does not capture the whitespace. So:

  1. Only up to the first whitespace of what you type into server's stdin will be stored in msg
  2. Newline will not be stored in msg.

But your client is doing

        bytes, err := connBuf.ReadBytes('\n')

The \n never comes. The client never gets done reading that first msg.

bufio.NewScanner would be a better way to collect data from stdin, since you're likely to want to capture whitespace as well. Don't forget to append the newline to each line of text you send, because the client expects it!

Working code

I put these changes together into a working example on the playground. To get it working in that context, I had to make a few other changes too.

  • Running server and client in the same process
  • Hard coded 3 clients so the program ended in limited amount of time
  • Hard coded 10 receives in the client so program can end
  • Hard coded 3 server connections handled so program can end
  • Removed fmt.Scanln and have server just return the original message sent (because playground provides no stdin mechanism)

Should be enough to get you started.

Receiving data via TCP: MemoryStream contains more data than expected

The problem is here where you write data:

memoryStream.Write(
dataBuffer,
0,
numBytesLeftToReceive < dataBuffer.Length ? numBytesLeftToReceive : dataBuffer.Length);

You completely ignore the amount you received, instead you just check if there’s more data to be received than the buffet size and if there is you write the whole buffer.

You can see in your output sometimes you don’t receive a full buffer. Yet you still write the whole buffer.

Always write based on the amount you received. Don’t do any weird comparisons based on the length of the data:

memoryStream.Write(
dataBuffer,
0,
numBytesReceived);

TCP server receiving more data than expected

TCP is a streaming protocol. If you do several send operations at the client side after eachtother, TCP is going to combine them into one segment as it is trying to fill up to the mtu.

TCP will send if the mtu is full or if a continuous 50ms timer elapses, or if the client itself has to ack a packet that it received from the server.

TCP is a very complex protocol. There is also an algorithm in there that calculates a window size. Also this window size has influence on the size of the segments that are received at the client side.

Bottom line is because TCP is streaming protocol, there is no notion of a packet that you receive through the socket. You receive an arbitrary number of bytes that you have to append to some kind of receive buffer yourself depending on what you are doing. If you desire packets, then you have to prepend the data that you send with a length field and take the length into account at the server as well. This of course complicates the code. Or if you want to keep it simple, simply use UDP. UDP does support packets and what you send will, if the packet does not get lost somewhere, be received with the same size at the receiver.
But UDP is not reliable, the packet might get lost. TCP is reliable, is connection oriented, but is more complex.

Socket programming in general is not a beginners topic.



Related Topics



Leave a reply



Submit