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:
- Only up to the first whitespace of what you type into server's stdin will be stored in
msg
- 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
Conversion of System.Array to List
How to Directly Execute SQL Query in C#
Why Do These Division Equations Result in Zero
Pinvoke for C Function That Returns Char *
Uwp Binding in Style Setter Not Working
Mvc3 Razor Dropdownlistfor Enums
How Would You Compare Two Xml Documents
Read the Value of an Attribute of a Method
Adding Your Own HTMLhelper in ASP.NET MVC 3
Unauthorised Webapi Call Returning Login Page Rather Than 401
How to Detect Windows Shutdown or Logoff
Making Entity Class Closed for Changes
Multipart Forms from C# Client
How to Get Printer Info in .Net