I am making a multi-threaded TCP server, when I use recv() in the threads, they do not update/execute/run infinitely (looping), unless recv() actually receives some data.
Here is a code snippet from inside the loop.
if( seconds < 15 ){
printf("%f seconds passed: \r", seconds);
if ( (read_size = recv(sock , client_message , 512 , 0)) > 0 )
{
//Send the message back to client
reply_message = client_message;
(void)write(sock, reply_message, strlen(reply_message));
}
}else{
// ... blah blah blah
}
If I comment out the internal IF statement, the thread runs & outputs printf() as fast as it can. When the IF statement is included, the thread waits on recv() and will not update ( printf() isn't printed ) until recv() has received data :/
Any ideas?
From recv(2) - Linux man page (see here):
If no messages are available at the socket, the receive calls wait for
a message to arrive, unless the socket is nonblocking (see fcntl(2)),
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.
So it's the way how recv works. If you want it to return immediately you should use non-blocking mode (see fcntl and select desriptions).
// sock is the socket you want to make non-blocking
int status = fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
// handle the error
if(status == -1) {
...
}
If you want to check if there anything to read in socket
int count = 0;
ioctl(sock, FIONREAD, &count);
count is the number of bytes available in the socket
Related
This continues to occur for an infinite amount of time until a valid event occurs on the corresponding socket. Then again, it goes back to normal behavior. Unable to trace the trigger for this issue.
What other events should I look for in the sockets other than the events I have registered for and why? I have currently registered for POLLIN & POLLHUP.
while ( 1 )
{
//Calling POLL Function;
//Sockets in List ( One Server Socket TCP )
//Sockets of Open TCP Connections
int rv = poll ( ufds , nfds , - 1 );
if (rv == -1)
{
//Error Occured in POLL
}
else if ( rv == 0 )
{
//Time out fromData Recieved
}
else if ( rv > 0 )
{
//Look for events POLLIN or POLLHUP and act correspondingly
}
}
(MOST POSSIBLE)Trigger for the issue -
//Called by Main Thread when another thread is
//polling on the respective socket_fd
recv(socket_fd, buffer, 1024, MSG_PEEK | MSG_DONTWAIT);
I am doing a MSG_PEEK to see whether the peer connected to this socket is alive.
The POLLHUP, POLLERR and POLLNVAL events will cause poll to return even if these events have not been specified in events (in fact, setting these in events will be ignored). Check revents to see if any of these events happened for your file descriptors.
I need to perform some operations only after the time a TCP connection is fully closed, that's to say - all the data segments, as well as the finishing routine (FIN-ACK or RST) have been performed and done, and no packets will be sent on the wires.
Since closesocket() is not synchronous and could return before a full close of the connection and socket, I've used the SO_LINGER option to get the moment of closing.
According to the instructions in the MSDN for closesocket, and to the fact that my socket is non-blocking (and thus asynchronous), I wrote this code:
int ret;
/* config 2 secs of linger */
struct linger lng = {1, 2};
setsockopt(s, SOL_SOCKET, SO_LINGER, (const char*)&lng, sizeof(lng));
/* graceful close of TCP (FIN-ACK for both sides) */
shutdown(s, SD_BOTH);
/* linger routine for asynchronous sockets according to msdn */
do {
ret = closesocket(s);
} while (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK);
/* my code to be run immediately after all the traffic */
printf("code to run after closing");
However, the closesocket call returns zero (success; instead of getting into the loop) and I see in Wireshark that my final printing is called before all the packets were sent, so - it looks like the linger isn't working.
By the way, the functions I used to open and connect the asynchronous socket were socket(), WSAIoctl() and its lpfnConnectEx() callback.
What's the reason that the lingered closesocket return before a full finish of the TCP connection? Is there a solution?
I am trying to make a simple client-server chat program. On the client side I spin off another thread to read any incomming data from the server. The problem is, I want to gracefully terminate that second thread when a person logs out from the main thread. I was trying to use a shared variable 'running' to terminate, problem is, the socket read() command is a blocking command, so if I do while(running == 1), the server has to send something before the read returns and the while condition can be checked again. I am looking for a method (with common unix sockets only) to do a non-blocking read, basically some form of peek() would work, for I can continually check the loop to see if I'm done.
The reading thread loop is below, right now it does not have any mutex's for the shared variables, but I plan to add that later don't worry! ;)
void *serverlisten(void *vargp)
{
while(running == 1)
{
read(socket, readbuffer, sizeof(readbuffer));
printf("CLIENT RECIEVED: %s\n", readbuffer);
}
pthread_exit(NULL);
}
You can make socket not blockable, as suggested in another post plus use select to wait input with timeout, like this:
fd_set input;
FD_ZERO(&input);
FD_SET(sd, &input);
struct timeval timeout;
timeout.tv_sec = sec;
timeout.tv_usec = msec * 1000;
int n = select(sd + 1, &input, NULL, NULL, &timeout);
if (n == -1) {
//something wrong
} else if (n == 0)
continue;//timeout
if (!FD_ISSET(sd, &input))
;//again something wrong
//here we can call not blockable read
fcntl(socket, F_SETFL, O_NONBLOCK);
or, if you have other flags:
int x;
x=fcntl(socket ,F_GETFL, 0);
fcntl(socket, F_SETFL, x | O_NONBLOCK);
then check the return value of read to see whether there was data available.
note: a bit of googling will yield you lots of full examples.
You can also use blocking sockets, and "peek" with select with a timeout. It seems more appropriate here so you don't do busy wait.
The best thing is likely to get rid of the extra thread and use select() or poll() to handle everything in one thread.
If you want to keep the thread, one thing you can do is call shutdown() on the socket with SHUT_RDWR, which will shut down the connection, wake up all threads blocked on it but keep the file descriptor valid. After you have joined the reader thread, you can then close the socket. Note that this only works on sockets, not on other types of file descriptor.
Look for function setsockopt with option SO_RCVTIMEO.
SERVER CODE
...
client_socket = accept(server_socket, (struct sockaddr *) &client_address, &client_address_len);
...
for (;;) {
if ( recv(client_socket, recived_buffer, MAX_MSG_LENGTH, 0) < 0 ) {
perror("ERROR leyendo el socket");
exit(1)
}
}
if i kill the client the server lopps indefinitely...
Any tip?
When a client closes a connection, the server-side recv() call will return a value of 0.
From the recv(2) manpage:
Return Value
These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
It may also be important to note that the recv() call will block until there is data available to read. If you want to not block, you need to be sure to set the socket to non-blocking or use select() or poll() to see if there is incoming data before calling recv().
recv returns 0 - when the peer closes the connection, the other part interprets it as an EOF
What is the difference between read() and recv(), and between send() and write() in socket programming in terms of performances, speed and other behaviors?
The difference is that recv()/send() work only on socket descriptors and let you specify certain options for the actual operation. Those functions are slightly more specialized (for instance, you can set a flag to ignore SIGPIPE, or to send out-of-band messages...).
Functions read()/write() are the universal file descriptor functions working on all descriptors.
Per the first hit on Google
read() is equivalent to recv() with a flags parameter of 0. Other values for the flags parameter change the behaviour of recv(). Similarly, write() is equivalent to send() with flags == 0.
read() and write() are more generic, they work with any file descriptor.
However, they won't work on Windows.
You can pass additional options to send() and recv(), so you may have to used them in some cases.
I just noticed recently that when I used write() on a socket in Windows, it almost works (the FD passed to write() isn't the same as the one passed to send(); I used _open_osfhandle() to get the FD to pass to write()). However, it didn't work when I tried to send binary data that included character 10. write() somewhere inserted character 13 before this. Changing it to send() with a flags parameter of 0 fixed that problem. read() could have the reverse problem if 13-10 are consecutive in the binary data, but I haven't tested it. But that appears to be another possible difference between send() and write().
Another thing on linux is:
send does not allow to operate on non-socket fd. Thus, for example to write on usb port, write is necessary.
On Linux I also notice that :
Interruption of system calls and library functions by signal handlers
If a signal handler is invoked while a system call or library function call is blocked, then either:
the call is automatically restarted after the signal handler returns; or
the call fails with the error EINTR.
... The details vary across UNIX systems; below, the details for Linux.
If a blocked call to one of the following interfaces is interrupted
by a signal handler, then the call is automatically restarted after
the signal handler returns if the SA_RESTART flag was used; otherwise the call fails with the error EINTR:
read(2), readv(2), write(2), writev(2), and ioctl(2) calls on "slow" devices.
.....
The following interfaces are never restarted after being interrupted by a signal handler, regardless of the use of SA_RESTART; they
always fail with the error EINTR when interrupted by a signal handler:
"Input" socket interfaces, when a timeout (SO_RCVTIMEO) has been set on the socket using setsockopt(2): accept(2), recv(2),
recvfrom(2), recvmmsg(2) (also with a non-NULL timeout argument), and recvmsg(2).
"Output" socket interfaces, when a timeout (SO_RCVTIMEO) has been set on the socket using setsockopt(2): connect(2), send(2),
sendto(2), and sendmsg(2).
Check man 7 signal for more details.
A simple usage would be use signal to avoid recvfrom blocking indefinitely.
An example from APUE:
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>
#define BUFLEN 128
#define TIMEOUT 20
void
sigalrm(int signo)
{
}
void
print_uptime(int sockfd, struct addrinfo *aip)
{
int n;
char buf[BUFLEN];
buf[0] = 0;
if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen) < 0)
err_sys("sendto error");
alarm(TIMEOUT);
//here
if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) < 0) {
if (errno != EINTR)
alarm(0);
err_sys("recv error");
}
alarm(0);
write(STDOUT_FILENO, buf, n);
}
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err;
struct sigaction sa;
if (argc != 2)
err_quit("usage: ruptime hostname");
sa.sa_handler = sigalrm;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, NULL) < 0)
err_sys("sigaction error");
memset(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_DGRAM;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
err_quit("getaddrinfo error: %s", gai_strerror(err));
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if ((sockfd = socket(aip->ai_family, SOCK_DGRAM, 0)) < 0) {
err = errno;
} else {
print_uptime(sockfd, aip);
exit(0);
}
}
fprintf(stderr, "can't contact %s: %s\n", argv[1], strerror(err));
exit(1);
}
"Performance and speed"? Aren't those kind of ... synonyms, here?
Anyway, the recv() call takes flags that read() doesn't, which makes it more powerful, or at least more convenient. That is one difference. I don't think there is a significant performance difference, but haven't tested for it.
The only difference between recv() and read() is the presence of flags. With a zero flags argument, recv() is generally equivalent to read()
you can use write() and read() instead send() and recv() but send() and recv() offer much greater control over your data transmission