I'm having a problem where calling recv() system call does not block. I have a client-server structure setup at the moment, and the problem I am having is I send the server one message, while the server is set up so that it's something like:
while (1) {
char buf[1024];
recv(fd, buf, sizeof(buf), flags);
processMsg(buf);
}
It receives the first message correctly, but the recv() does not block and "receives" trash data which is not what is desired. I'd like to react to messages only when they are sent. Can anyone advise?
recv() does not necessarily block until the full request is fulfilled but can return a partial request. The return code will inform you of how many bytes were actually received which can be less than you requested. Even if you specify a MSG_WAITALL flag it can return less due to a signal, etc.
On posix systems, in blocking mode recv will only block until some data is present to be read. It will then return that data, which may be less than requested, up to the amount requested. In non-blocking mode recv will return immediately if there is zero bytes of data to be read and will return -1, setting errno to EAGAIN or EWOULDBLOCK.
The upshot is that normally you will call recv in a loop until you get the amount you want while also checking for return codes of 0 (other side disconnected) or -1 (some error).
I can't speak to windows behavior.
There's two possibilities: either an error is occurring, or the socket is set to non-blocking mode. To see if an error is occurring, check the return value of recv:
while() {
char buf[1024];
int ret = recv(,buf,,)
if(ret < 0) {
// handle error
printf("recv error: %s\n", strerror(errno));
} else {
// only use the first ret bytes of buf
processMsg(buf, ret);
}
}
To put the socket into non-blocking mode, or to query if a socket is in non-blocking mode, use fcntl(2) with the O_NONBLOCK flag:
// Test if the socket is in non-blocking mode:
if(fcntl(sockfd, F_GETFL) & O_NONBLOCK) {
// socket is non-blocking
}
// Put the socket in non-blocking mode:
if(fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK) < 0) {
// handle error
}
Note that unless you're explicitly changing the blocking behavior, the socket should be blocking by default, so most likely an error is occurring.
If you're on windows, run wsagetlasterror() function and look at the return value.
http://msdn.microsoft.com/en-us/library/ms741580%28v=vs.85%29.aspx
If you're on a posix compliant system look at errno
http://pubs.opengroup.org/onlinepubs/009695399/functions/errno.html
Related
I'm trying to send data to the connected client, even when the client did not send me a message first.
This is my current code:
while (true) {
// open a new socket to transmit data per connection
int sock;
if ((sock = accept(listen_sock, (sockaddr *) &client_address, &client_address_len)) < 0) {
logger.log(TYPE::ERROR, "server::could not open a socket to accept data");
exit(0);
}
int n = 0, total_received_bytes = 0, max_len = 4096;
std::vector<char> buffer(max_len);
logger.log(TYPE::SUCCESS,
"server::client connected with ip address: " + std::string(inet_ntoa(client_address.sin_addr)));
// keep running as long as the client keeps the connection open
while (true) {
n = recv(sock, &buffer[0], buffer.size(), 0);
if (n > 0) {
total_received_bytes += n;
std::string str(buffer.begin(), buffer.end());
KV key_value = kv_from(vector_from(str));
messaging.set_command(key_value);
}
std::string message = "hmc::" + messaging.get_value("hmc") + "---" + "sonar::" + messaging.get_value("sonar") + "\n";
send(sock, message.c_str(), message.length(), 0);
}
logger.log(TYPE::INFO, "server::connection closed");
close(sock);
}
I thought by moving the n = recv(sock, &buffer[0], buffer.size(), 0); outside the while condition that it would send the data indefinitely, but that is not what happened.
Thanks in advance.
Solution
Adding MSG_DONTWAIT to the recv function enabled non-blocking operations which I was looking for.
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
I am writing the client side of the Socket. When there is something to read my code works fine but when there is nothing to read, the recv never returns. Help please.
Code:
m_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in dest;
if ( m_socket )
{
memset(&dest, 0, sizeof(dest)); /* zero the struct */
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(address); /* set destination IP number */
dest.sin_port = htons(port);
if (connect(m_socket, (struct sockaddr *)&dest, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
return false;
}
else
{
std::vector<char> inStartup1(2);
int recvReturn = recv(Socket, &inStartup1.at(0), inStartup1.size(), 0);
}
recv is a blocking call. This would help you:-
The recv() call is normally used only on a connected socket.It returns the length of the message on successful completion. If a message is too long to fit in the supplied buffer, excess bytes may be discarded DEPENDING on the type of socket the message is received from.
If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking, in which case the value -1 is returned and the external variable errno is set to EAGAIN or EWOULDBLOCK. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.
Taking this one step further, on a server this is how you would correctly handle a connection (socket or serial port does not matter):
make the socket/port non-blocking: this is the first important step; it means that recv() will read what is available (if anything) and return the number of read bytes or -1 in case of an error.
use select(), with a timeout, to find out when data becomes available. So now you wait for a certain amount of time for data to become available and than read it.
The next problem to handle is making sure you read the full message. Since there is no guarantee that the whole message will be available when you call recv(), you need to save whatever is available and go back to select() and wait for the next data to become available.
Put everything in a while(cond) construct to make sure you read all the data.
The condition in the while is the only thing left to figure out - you either know the length of the expected message or you use some delimiters to mark the end of the message.
Hope this helps!
Why doesn't send() in winsock guarantee delivery of the all bytes you request?
This is TCP and it's blocking sockets.
Similarly, this happens when non-blocking. How can you guarantee that you send everything?
I've noticed recv() does the same.
If it didn't send everything, just call send again on the rest. If blocking, you can do it immediately. If non-blocking, you can either wait or use a socket discovery method (like select or I/O completion ports). The same goes for recv. If you didn't get all you wanted, call recv again. This is one of the reasons both recv and send return the number of bytes sent or received.
The number of bytes you pass to send or recv is just a limit. It can send less than that (though, unless non-blocking, usually won't). But it can definitely receive less than that. (The OS has no control over how much data it receives or when it receives it.)
TCP is implemented for you. But if you have an application protocol that involves application-level messages, then the application has to implement them. It won't happen by magic. TCP doesn't "glue the bytes together" into a message for you. TCP is a byte-stream protocol, not a message protocol. If you want messages, you have to implement them.
This behaviour is "by design".
You can use an outer loop as shown in this example:
int sendBuffer (SOCKET ClientSocket, const char *buf, int len, int flags)
{
int num_left = len;
int num_sent;
int err = 0;
const char *cp = buf;
while (num_left > 0)
{
num_sent = send(ClientSocket, cp, num_left, flags);
if (num_sent < 0)
{
err = SOCKET_ERROR;
break;
}
assert(num_sent <= num_left);
num_left -= num_sent;
cp += num_sent;
}
return (err == SOCKET_ERROR ? SOCKET_ERROR : len);
}
send tells you what it was able to send via its return value.
Loop until send has cumulatively sent all the data or returns an error.
I'm having a strange problem while attempting to transform a blocking socket server into a nonblocking one. Though the message was only received once when being sent with blocking sockets, using nonblocking sockets the message seems to be received an infinite number of times.
Here is the code that was changed:
return ::write(client, message, size);
to
// Nonblocking socket code
int total_sent = 0, result = -1;
while( total_sent < size ) {
// Create a temporary set of flags for use with the select function
fd_set working_set;
memcpy(&working_set, &master_set, sizeof(master_set));
// Check if data is available for the socket - wait 1 second for timeout
timeout.tv_sec = 1;
timeout.tv_usec = 0;
result = select(client + 1, NULL, &working_set, NULL, &timeout);
// We are able to write - do so
result = ::write(client, &message[total_sent], (size - total_sent));
if (result == -1) {
std::cerr << "An error has occured while writing to the server."
<< std::endl;
return result;
}
total_sent += result;
}
return 0;
EDIT: The initialization of the master set looks like this:
// Private member variables in header file
fd_set master_set;
int sock;
...
// Creation of socket in class constructor
sock = ::socket(PF_INET, socket_type, 0);
// Makes the socket nonblocking
fcntl(sock,F_GETFL,0);
FD_ZERO(&master_set);
FD_SET(sock, &master_set);
...
// And then when accept is called on the socket
result = ::accept(sock, NULL, NULL);
if (result > 0) {
// A connection was made with a client - change the master file
// descriptor to note that
FD_SET(result, &master_set);
}
I have confirmed that in both cases, the code is only being called once for the offending message. Also, the client side code hasn't changed at all - does anyone have any recommendations?
fcntl(sock,F_GETFL,0);
How does that make the socket non-blocking?
fcntl(sock, F_SETFL, O_NONBLOCK);
Also, you are not checking if you can actually write to the socket non-blocking style with
FD_ISSET(client, &working_set);
I do not believe that this code is really called only once in the "non blocking" version (quotes because it is not really non-blocking yet as Maister pointed out, look here), check again. If the blocking and non blocking versions are consistent, the non blocking version should return total_sent (or size). With return 0 instead caller is likely to believe nothing was sent. Which would cause infinite sending... is it not what's happening ?
Also your "non blocking" code is quite strange. You seem to use select to make it blocking anyway... Ok, with a timeout of 1s, but why don't you make it really non blocking ? ie: remove all the select stuff and test for error case in write() with errno being EWOULDBLOCK. select or poll are for multiplexing.
Also you should check errors for select and use FD_ISSET to check if socket is really ready. What if the 1 s timeout really happen ? Or if select is stopped by some interruption ? And if an error occurs in write, you should also write which error, that is much more useful than your generic message. But I guess this part of code is still far from finished.
As far as I understand your code it should probably look somewhat like that (if the code is running in an unique thread or threaded, or forking when accepting a connection would change details):
// Creation of socket in class constructor
sock = ::socket(PF_INET, socket_type, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
// And then when accept is called on the socket
result = ::accept(sock, NULL, NULL);
if (result > 0) {
// A connection was made with a client
client = result;
fcntl(client, F_SETFL, O_NONBLOCK);
}
// Nonblocking socket code
result = ::write(client, &message[total_sent], (size - total_sent));
if (result == -1) {
if (errno == EWOULDBLOCK){
return 0;
}
std::cerr << "An error has occured while writing to the server."
<< std::endl;
return result;
}
return size;
For a TCP blocking socket, is it safe to call:
if(SOCKET_ERROR != recv(s, NULL, 0, 0))
//...
to detect errors?
I thought it was safe, then I had a situation on a computer that it was hanging on this statement. (was with an ssl socket if that matters). I also tried passing in the MSG_PEEK flag with a buffer specified but I also had a hang there.
What is the alternative?
In addition to other answers - here's a handy little function to get the pending socket error:
/* Retrives pending socket error. */
int get_socket_error( int sockfd )
{
int error;
socklen_t len( sizeof( error ));
if ( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &len ) < 0 )
error = errno;
return error;
}
You did say you were using a blocking socket, but you should use select instead (even if you set it unblocking before the select call). It allows you to poll a file descriptor and see if there is data waiting, or if there is an error.
The call itself is "safe" in a sense that it should work as documented, however you must realize that recv is a blocking receive call. This means that the call will block the executing thread until data arrives on the socket. This can cause your application to "hang" if you are not using a different thread to do your receive, or checking to see if data is available before call receive (select).