Winsock: Echo server replying twice, when I just programmed it to do one send() call - c++

I am doing a simple TCP server in C++ for Windows to echo incoming data. I have a problem with it. Before I explain my problem, I have to say that Winsock is properly set up and this problem happens with any IP address as the source.
The general behaviour when a connection is established is this:
In the loop that runs while connection still alive, it must echo data, and precede it with REPLY word.
To do that, I'm currently using two send() calls:
One call sending "REPLY " alone.
Another call just sending back received data.
But using Putty Client, I'm getting this:
REPLY data_echoed REPLY.
Why REPLY is sent after the last send call if it was the first??? I'll post a little code where the problem happens:
//Reply to client
message = "HELLO CLIENT!! READY TO ECHO.\n";
send(new_socket, message, strlen(message), 0);
///Enter into a loop until connection is finished.
printf("%s \n\n", "Incoming data goes here: ");
do{
///Clear buffer and receive data.
memset(buffer, 0, sizeof(buffer));
ret = recv(new_socket, buffer, sizeof(buffer), 0);
printf("%s", buffer);
///Send a REPLY WORD and the data echoed.
send(new_socket, "REPLY\r\n", 7, 0);
send(new_socket, buffer, sizeof(buffer), 0);
}while(ret != SOCKET_ERROR);
What is wrong with that? I'll remove the first call, and the double effect disappears. Why I can't do two send calls one after other?

You ignore the return value of recv until after you send REPLY, so no matter what happens, you send REPLY followed by the contents of the buffer. After you echo the first time, something happens, and no matter what it is, you send REPLY.
Bluntly, it doesn't look like you understand the very basics of TCP. We used to have a rule that before anyone can do anything with TCP, they must memorize and completely understand the following statement: "TCP is a byte-stream protocol that does not preserve application message boundaries."
Your code pretends that it is receiving and echoing application-level messages. But there is no code to actually implement application-level messages. TCP has no support for application-level messages, so if you want them, you have to implement them. You clearly want them. You also have not implemented them.
Do newline characters delimit messages? If so, where's the code to find them in the data stream? If not, what does?

Related

Recvfrom: wait for full message (variable size message, thread)

I have a UDP client that is sending messages to a server, at a specified rate. The rate needs to be constant, so I decided to try to do my receiving of replies in a separate thread to avoid blocking or delaying on recvfrom(). Is it at all possible to 'wait' for a full message before receiving? What would be the best strategy to go about doing this?
while (true)
{
//std::this_thread::sleep_for(std::chrono::milliseconds(5000));
if (recvfrom(threadSock, ReceiveBuf, BufLength, 0, 0, 0) == SOCKET_ERROR)
{
printf("Thread Receive failed with error %ld\n", GetLastError());
break;
}
else
{
printf("Reply received: %s\n\n", ReceiveBuf);
}
memset(ReceiveBuf, '\0', BufLength);
}
Above is my receiving code. Currently, only the first 8 characters of a reply are being read into the buffer (the buffer is 512 bytes).
How can I wait for a full message (bearing in mind the message lengths are variable).
Is this even possible? Perhaps there is a better approach.
Thanks in advance.
EDIT: I should clarify the prints are for testing only. They won't be in the final result, as printing from a thread gives weird inline prints.
According to MSDN:
The recvfrom function receives a datagram and stores the source address.
For message-oriented sockets, data is extracted from the first enqueued message, up to the size of the buffer specified. If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost. For UDP if the packet received contains no data (empty), the return value from the recvfrom function function is zero.
Thus, you can't receive a part of the incoming message, the receive returns only when the OS can process and return an enqueued datagram.
In the interest of completeness, and the small chance anyone suffering from similar confusion finds this, solution follows:
Yes, it was a silly question, I should've realised recvfrom waits for a full datagram. The problem was with my server.
It was an issue of the server not sending the full data. I'm not sure as to the exact cause, but to fix it I converted the char* my reply was being stored to (and printing correctly) to a char[], which, when sent, worked fine.

What about partial recv() on two byte header containing message length?

I have been reading some socket guides such as Beej's guide to network programming. It is quite clear now that there is no guarantee on how many bytes are received in a single recv() call. Therefore a mechanism of e.g. first two bytes stating the message length should be sent and then the message. So the receiver receives the first two bytes and then receives in a loop until the whole message has been received. All good and dandy!?
I was asked by a colleague about messages going out of sync. E.g. what if, somehow, I receive two bytes in once recv() call that are actually in the middle of the message itself and it would appear as a integer of some value? Does that mean that the rest of the data sent will be out of sync? And what about receiving the header partially, i.e. one byte at a time?
Maybe this is overthinking, but I can't find this mentioned anywhere and I just want to be sure that I would handle this if it could be a possible threat to the integrity of the communication.
Thanks.
It is not overthinking. TCP presents a stream so you should treat it this way. A lot of problems concerning TCP are due to network issues and will probably not happen during development.
Start a message with a (4 byte) magic that you can look for followed by a (4 byte) length in an expected order (normally big endian). When receiving, read each byte of the header at the time, so you can handle it anyway the bytes were received. Based on that you can accept messages in a lasting TCP connection.
Mind you that when starting a new connection per message, you know the starting point. However, it doesn't hurt sending a magic either, if only to filter out some invalid messages.
A checksum is not necessary because TCP shows a reliable stream of bytes which was already checked by the receiving part of TCP, and syncing will only be needed if there was a coding issue with sending/receiving.
On the other hand, UDP sends packets, so you know what to expect, but then the delivery and order is not guaranteed.
Your colleague is mistaken. TCP data cannot arrive out of order. However you should investigate the MSG_WAITALL flag to recv() to overcome the possibility of the two length bytes arriving separately, and to eliminate the need for a loop when receiving the message body.
Its your responsibility to make you client and server syncing together, how ever in TCP there is no out of order delivery, if you got something by calling recv() you can think there isn't anything behind that that you doesn't received.
So the question is how to synchronize sender and receiver ? its easy, as stefaanv said, sender and receiver are knowing their starting point. so you can define a protocol for your network communication. for example a protocol could be defined this way :
4 bytes of header including message type and payload length
Rest of message is payload length
By this, you have to send 4 byte header before sending actual payload, then sending actual payload followed.
Because TCP has garauntied Inorder reliable delivery, you can make two recv() call for each pack. one recv() call with length of 4 bytes for getting next payload size, and another call to recv() with size specified in header. Its necessary to make both recv() blocking to getting synchronized all the time.
An example would be like this:
#define MAX_BUF_SIZE 1024 // something you know
char buf[MAX_BUF_SIZE];
int recvLen = recv(fd, buff, 4, MSG_PEEK);
if(recvLen==4){
recvLen = recv(fd, buff, 4);
if(recvLen != 4){
// fatal error
}
int payloadLen = extractPayloadLenFromHeader(buf);
recvLen = recv(fd, buff, payloadLen, MSG_PEEK);
if(recvLen == payloadLen){
recvLen = recv(fd, buff, payloadLen); // actual recv
if(recvLen != payloadLen){
// fatal error
}
// do something with received payload
}
}
As you can see, i have first called recv with MSG_PEEK flag to ensure is there really 4 bytes available or not, then received actual header. same for payload

Operation canceled error in async_write

I am trying to send a large amount of data around 50KByte or above over a TCP socket using the following command in C++:
boost::asio::async_write(sock, boost::asio::buffer(sbuff, slen),
boost::bind((&send_handler), placeholders::error));
Where sbuff is a pointer to the data to be transmitted, and slen is the length of the data.
Sometimes the operation successes and sometimes I get an error with Operation cancelled
Here is the code part for the receiver, waiting for a specific amount of the data to be received.
boost::asio::async_read(_sock,
boost::asio::buffer(rbuf, rlen),
boost::bind(&session::handle_read_payload,
this,
placeholders::bytes_transferred,
placeholders::error));
void session::handle_read_payload(buffer<uint8> &buff, size_t rbytes, const boost::system::error_code &e)
Where rlen is the number of the bytes to wait to receive. And rbuf is a pointer to where I store the received bytes.
I checked the flow of the TCP packets between the two machines using Wireshark and I found that suddenly the receiver sends back a packet with FIN flag set to the sender, which terminates the connection.
So can anyone tell me what might be the root of the problem? IS there any problem with my code?
Does it matter if I call _acceptor.listen(); before async_accept. Because when I tested without _acceptor.listen(); , it works perfectly. So what would be the difference?
From the discussion in the comments to the question, it sounds very much like there is a disagreement between the sender and the receiver about the size of the message being sent.
The receiver receives what it thinks is a complete message then closes the socket while the sender still thinks there is more data that the receiver has not accepted.
To diagnose the problem, I suggest that you display slen on the sender side, and display rlen on the receiver side before issuing the respective read/write requests (by display I mean write to a log or to std::cerr or whatever other approach works for your application.) If the two numbers are not equal you know where to look for the underlying cause of the problem. If they are equal -- then more investigation will be needed.

C++ network programing in linux: Server Questions

I am learning how to network program using c/c++ and I have created a server(TCP) that is suppose to respond in specific ways to messages from a client in order to do this I created a class that the server class passes the message to and returns a string to report back to the client.
Here is my problem sometimes it reports the correct string back other times if just repeats what I sent to the message handler. Which no where in the code do I have it return what was passed in. So I am wondering am I handling getting the message correctly?
Secondly, I am unsure of how to keep a connection open in a while loop to continually pass messages back and forth. You can see how I did it in the code below but I am pretty sure this is incorrect, any help on this would be great. Thanks!
if (!fork())
{ // this is the child process
close(sockfd); // child doesn't need the listener
while ((numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0)) > 0)
{
//numbytes = recv(new_fd, buf, MAXDATASIZE-1, 0);
buf[numbytes-1] = '\0';
const char* temp = ash.handleMessage(buf).c_str();
int size_of_temp = ash.handleMessage(buf).length();
send(new_fd, temp, size_of_temp, 0);
//send(new_fd, temp, size_of_temp+1, 0);
}
}//end if
Please excuse my ghetto code
Handles the message
Class Method handler uses
If your learning about sockets you should also know that you can't assume that what you send() as a "complete message", will be delivered as a complete message.
If you send() some big data from your client you might need to use multiple recv() on the server (or vice versa) to read it all. This is a big difference of how files usually work...
If you'r designing your own protocol you can opt to also send the messages length, like [LEN][message]. An easy example would be if the strings you send are limited to 256 bytes you can start with send()ing a short representing the strings length,
Or easier, decide that you use line-feeds (newline - \n) to terminate messages. The the protocol would look like
"msg1\nmsg2\n"
then you would have to recv(), and append the data, until you get a newline. This is all I can muster right now, there are a lot of great examples on the internet, but I would recommend getting the source of some "real" program and look at how it handles its network.
You are calling handleMessage twice. You didn't post the code, but it looks like you're returning a string. It might be better to do:
string temp = ash.handleMessage(buf);
int size_of_temp = temp.length();
This would avoid repeating any action that takes place in handleMessage.

Handling partial return from recv() TCP in C

I've been reading through Beej's Guide to Network Programming to get a handle on TCP connections. In one of the samples the client code for a simple TCP stream client looks like:
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Client: received '%s'\n", buf);
close(sockfd);
I've set the buffer to be smaller than the total number of bytes that I'm sending. I'm not quite sure how I can get the other bytes. Do I have to loop over recv() until I receive '\0'?
*Note on the server side I'm also implementing his sendall() function, so it should actually be sending everything to the client.
See also 6.1. A Simple Stream Server in the guide.
Yes, you will need multiple recv() calls, until you have all data.
To know when that is, using the return status from recv() is no good - it only tells you how many bytes you have received, not how many bytes are available, as some may still be in transit.
It is better if the data you receive somehow encodes the length of the total data. Read as many data until you know what the length is, then read until you have received length data. To do that, various approaches are possible; the common one is to make a buffer large enough to hold all data once you know what the length is.
Another approach is to use fixed-size buffers, and always try to receive min(missing, bufsize), decreasing missing after each recv().
The first thing you need to learn when doing TCP/IP programming: 1 write/send call might take
several recv calls to receive, and several write/send calls might need just 1 recv call to receive. And anything in-between.
You'll need to loop until you have all data. The return value of recv() tells you how much data you received. If you simply want to receive all data on the TCP connection, you can loop until recv() returns 0 - provided that the other end closes the TCP connection when it is done sending.
If you're sending records/lines/packets/commands or something similar, you need to make your own protocol over TCP, which might be as simple as "commands are delimited with \n".
The simple way to read/parse such a command would be to read 1 byte at a time, building up a buffer with the received bytes and check for a \n byte every time. Reading 1 byte is extremely inefficient, so you should read larger chunks at a time.
Since TCP is stream oriented and does not provide record/message boundaries it becomes a bit more tricky - you'd
have to recv a piece of bytes, check in the received buffer for a \n byte, if it's there - append the bytes to previously received bytes and output that message. Then check the remainder of the buffer after the \n - which might contain another whole message or just the start of another message.
Yes, you have to loop over recv() until you receive '\0' or an
error happen (negative value from recv) or 0 from recv().
For the first option: only if this zero is part of your
protocol (the server sends it). However from your code it seems that
the zero is just to be able to use the buffer content as a
C-string (on the client side).
The check for a return value of 0 from recv:
this means that the connection was closed (it could be part
of your protocol that this happens.)