I am having a problem with sendto.
I have a receiver who receives UPD packets with recvfrom and then replies to the sender using sendto.
Unfortunately, I am getting errno 11 (Resource temporarily unavailable). I am using two sockets.
The first packet is actually sent but not the ones afterwards:
sendto :: Success
error: 0.
sendto :: Resource temporarily unavailable
error: 11.
sendto :: Resource temporarily unavailable
...
This is an extract of my code:
int sockfd, sockSend;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
perror("socket");
if ((sockSend = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
perror("socket");
if (fcntl(sockfd, F_SETOWN, getpid()) < 0) {
perror("fcntl");
}
if (fcntl(sockfd, F_SETFL, O_RDONLY | O_NONBLOCK | FASYNC) < 0) {
perror("fcntl");
}
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
< 0)
perror("bind");
And in a SIGIO handler:
len = sizeof(recv_addr);
char buffer[payload];
bzero(buffer, payload);
n = recvfrom(sockfd, buffer, payload, MSG_DONTWAIT, (struct sockaddr *)&recv_addr, &len);
while (n > 0) {
sprintf(response, "%d\n%d\n%d\n", items, target_buf, pb_sp);
sendto(sockSend, response, strlen(response), 0, (struct sockaddr *) &recv_addr, sizeof(recv_addr));
// sleep(1);
perror("sendto :");
printf("error: %d.\n", errno);
}
Could this issue come because the port is still hot, and I need to wait before reusing it? I've tried to change port but it hasn't helped.
Update: If the sleep(1) is commented out, then the packets actually get send!
Thanks a lot for your help.
The error you are getting:
EAGAIN or EWOULDBLOCK: The socket is marked nonblocking and the requested operation would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.
You set the socket to non-blocking (O_NONBLOCK). The socket is still busy sending the previous message. You cannot send another until the first has finished sending. That's why sleeping helped.
Don't set it to non-blocking, or try again after select says you can.
If you have to set the socket to non-blocking, you can do it safely (and only?) using select:
select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking.
Related
How can I retry sending (let's say using a while loop or something similar) in the following code that I have, whenever I have a timeout? I abridged some parts of my code.
I am not familiar with C error codes and error handling so I don't know where to catch/handle the error and what error code to look for.
sock = socket(create socket....)
if (sock < 0 ) {
exit(EXIT_FAILURE);
}
servaddr initializations.....
sendto(sock, etc etc........);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&timeout,sizeof(timeout)) < 0) {
perror("Error");
}
addrlen = sizeof(servaddr);
if(recvfrom (sock, etc, etc......) < 0)
{
printf("revfrom failed.\n");
}
From man 7 socket:
SO_RCVTIMEO and SO_SNDTIMEO:
Specify the receiving or sending timeouts until reporting an
error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached, then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default), then the operation will never timeout. Timeouts only have effect for system calls that perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for select(2), poll(2), epoll_wait(2), and so on.
So, in your case, the code to keep trying if the timeout is reached would look something like this:
struct timeval timeout = {.tv_sec = 5, .tv_usec = 0};
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
perror("setsockopt failed");
// Handle error
}
// ...
while (sendto(sock, /*...*/) == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
// Some unexpected error happened.
perror("sendto failed");
}
// Otherwise it was a timeout, just continue trying.
}
Note that SO_SNDTIMEO is for sending, and SO_RCVTIMEO is for receiving. If you want to set both then do two setsockopt calls.
In any case, it seems to me like you are wasting your time with this. If you want to keep trying until you get data, then just don't bother doing any setsockopt, as the default behavior is to wait indefinitely until data is received:
If the timeout is set to zero (the default), then the operation will never timeout.
I'm trying to set socket options for a client socket returned from the accept() function. But they are not getting set correctly.
My aim is to time out the client after a particular time of inactivity. But the server should still be able to accept other client connections.
Below is my code where I set the socket option. Can you please suggest what is wrong?
while ((new_sock_fd = accept(socket_fd, (struct sockaddr *) &cli_addr, &clilen)) > 0)
{
if (new_sock_fd < 0)
printf("Accept Error");
else
{
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
if (setsockopt(new_sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
error("setsockopt failed\n");
if (setsockopt(new_sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
error("setsockopt failed\n");
pthread_create(&thread, NULL, client_handler, (void *) (intptr_t)new_sock_fd); //intptr_t is big enough to hold the integer prt
}
}
My aim is to time out the client after a particular time of
inactivity. [...] can you please suggest what when wrong..?
I suspect what's wrong is that you're misunderstanding what SO_RCVTIMEO and SO_SNDTIMEO are intended to do. From the man page:
SO_RCVTIMEO and SO_SNDTIMEO Specify the receiving or sending timeouts
until reporting an error. The argument is a struct timeval. If an
input or output function blocks for this period of time, and data has
been sent or received, the return value of that function will be the
amount of data transferred; if no data has been transferred and the
timeout has been reached then -1 is returned with errno set to EAGAIN
or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket
was specified to be nonblocking. If the timeout is set to zero (the
default) then the operation will never timeout.
... but it sounds like what you want is for the TCP connection be automatically closed after a certain amount of time with no traffic on the TCP connection, which is not the same thing as forcing a call to send() or recv() to return after a specified amount of time.
If what you are looking for is a mechanism to close an idle TCP connection, you can implement that yourself by recording the current time whenever data is sent or received on the socket. At a later time (e.g. after send() or recv() times out), you can subtract your recorded last-traffic-seen-at-time from the current time; if the difference is greater than your idle-timeout value, call close() on the socket yourself.
I have written a program using non-blocking connect() and select() combination to check the connection to a remote host at a
particular port. select() has some timeout value also, in my case 2.5s. I am testing the program to connect to a process running the SMTP service on the remote host which is
which is bound to port 25 . If I kill that process running on remote host , then also select() returning 1 to tell that writing (socket added to write fd_set ) to that process
is possible. What can be the reason behind this, and also Is it possible to use select() in this case. I tried using connect() which returns immediately when such connection is not possible but it doesn't work in case some timeout is required for connection, that is why I am using select().
select() doesn't tell you that reading or writing is possible, it just tells you that it won't block (or return the error EWOULDBLOCK if the socket is in non-blocking mode). A socket is always writable as long as the local socket buffer is not full. Also, if anything was sent after the remote process has died, you will receive a RST packet, and attempts to write after that will return ECONNRESET immediately. So the socket will be marked writable when that happens.
I was able to accomplish by using another connect() after select() function call.
Posting the code snippet
error = connect(soc, (struct sockaddr *)serveraddr, sizeof(struct sockaddr)) ;
if(error == 0){
DIAGC("vsrserv", 1, "Returning while connect is 0");
return 0;
}
if(errno != EINPROGRESS)
return -1;
int retVal = select (soc+1, &writeFD, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)(&timeout));
if (retVal == 0){
close(soc);
return -1;
}
socklen_t len = 0;
int m = getsockopt(soc, SOL_SOCKET, SO_ERROR, &error, &len) ;
if(m < 0){
close(soc);
return -1;
}
//connect() returns immediately if it is able to connect to that particular port
//Since select() returned 1 it means host was reachable so just need to verify the port on the remote host which we can do with another with connect() call
error = connect(soc, (struct sockaddr *)serveraddr, sizeof(struct sockaddr)) ;
if(error < 0){
close(soc);
return -1;
}
I have a blocking socket (at least it appears so in following code):
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
ERROR("%s: error opening socket", __func__);
return (RESP_ERROR);
}
t.tv_sec = timeout;
t.tv_usec = 0;
int rf = fcntl(sock, F_GETFD);
ERROR("fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);
if ((setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof (t)) < 0)
|| (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&t, sizeof (t)))) {
strerror_r(errno, err, 254);
ERROR("%s: error on setsockopt -> %s", __func__, err);
close(sock);
return (RESP_ERROR);
}
rf = fcntl(sock, F_GETFD);
ERROR("after select fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);
if (connect(sock, (struct sockaddr *)&dst, sizeof (dst)) != 0) {
strerror_r(errno, err, 254);
ERROR("%s: error on connect -> %s", __func__, err);
close(sock);
return (RESP_ERROR);
}
And this is from log:
Mar 6 10:42:04 tcpclient: fcntl ret=0, ret & O_NONBLOCK = 0
Mar 6 10:42:04 tcpclient: after select fcntl ret=0, ret & O_NONBLOCK = 0
Mar 6 10:42:14 tcpclient: authenticate: error on connect -> Operation now in progress
It appears this is a blocking socket but returns error typical for non-blocking? Linux is 2.6.18-308.el5. Any ideas?
If timeout is not 0 the call to connect() times out and returns. This happens independently of whether a connection was established or not.
From the moment the time-out expired connect() behaves as if called on a non-blocking socket.
Referring this case (verbatim from man connect and ignore "immediately" below):
EINPROGRESS
The socket is nonblocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use
getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explainâ
ing the reason for the failure).
Btw: Could someone confirm this is standard behaviour, and for this explicitly mentioned somewhere?
man 7 socket states (italics by me):
SO_RCVTIMEO and SO_SNDTIMEO
Specify the receiving or sending timeouts until reporting an error. [...] if no data has been transferred and the timeout has been reached then -1 is returned with errno set to EAGAIN or EWOULDBLOCK just as if the socket was
specified to be nonblocking. [...] Timeouts only have effect for system calls that perform socket I/O (e.g., read(2), recvmsg(2), send(2),
sendmsg(2)); timeouts have no effect for select(2), poll(2), epoll_wait(2), etc.
No word regarding connect()so I'm unsure my answer does hold.
Try it with if (connect(...) < 0). You may not be getting an error at all.
NB blocking mode is the default. You don't have to set it.
when I do 100 non-block socket connection in 1 thread,it is very slow(the number of connection increased one by one),but if I do a blocking socket connection in 100 parallel threads(one connect per thread), it is very fast(get done immediately )
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fcntl(sock, F_SETFL,O_NONBLOCK)!=0)
{
perror("fcntl nonblock");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,&reuseAddr, sizeof(reuseAddr))!=0)
{
perror("reuse addr");
return -1;
}
sAddr.sin_addr.s_addr = inet_addr(SRV_ADDR);
sAddr.sin_port = htons(1972);
if ((n=connect(sock, (const struct sockaddr *) &sAddr, sizeof(sAddr))) < 0)
{
if (errno !=EINPROGRESS) {
perror("client connect error");
return -1;
}
}
else if (n>=0)
{
printf("#%d connected\n",sock);
}
return sock;
Awesome question :-). Here's why I think this is happening. The standard says this:
If the connection cannot be established immediately and O_NONBLOCK is
set for the file descriptor for the socket, connect() shall fail and
set errno to [EINPROGRESS]
The question of course is what "immediately" means. I believe that "immediately" is actually some small time that allows the SYN, SYN-ACK, ACK to happen. If it didn't wait at all, it would have 0-chance of actually succeeding.
So basically:
The client sends a SYN
Waits (blocks) for a small period of time ("immediately") for a SYN-ACK.
Completes the connection
In doing so it returns successfully instead of EADDRINUSE.
Now, when using threads, each thread does this so nobody waits. They all just connect(2) and context switching allows everybody to do it almost simultaneously.