My requirement is to connect with the server if it is up ,the client will keep on trying to connect with the server till the successful connection.So I have created the socket fd using the socket() and try to connect using the connect().If the connect fails ,I close the fd using the close().
The expected behaviour is, when the next try the same file descriptor need to be generate by the socket().but for each try the new decriptor only gets created ,since I am closing the file decriptor in case of fail.What may be the issue.Can any one help me.
If you want to repeatedly attempt to connect to a server until a connection is established, just use a loop around a call to connect. socket only binds an endpoint and a file descriptor together.
while (1) {
state = connect(fd, &sa, sizeof sa);
if (state == 0) {
break
} else {
/* Is the server available yet? */
if (errno == ECONNREFUSED) {
/* No, continue trying to connect. */
continue;
} else {
/* Deal with other errors. */
}
}
}
Related
FINAL EDIT: Solution to problem was stated by the answer I have selected. The representative example code is shown in the diff here
EDIT: Full compile-able code at the bottom of the post.
I have this rudimentary multithreaded server that simply accepts a connection and is supposed to pass the file descriptor off to a thread to allow this thread to handle it directly until the client disconnects.
For some reason, even with the following code flow inside of the server, some clients "Fall through the cracks" and get stuck in limbo. (They never get handled by the server so they just hang after accepting the connection)
The following block is my server main running loop:
while(g_serv.b_running)
{
//printf("Awaiting connection.\n");
client_fd = accept(g_serv.serv_listener_fd,
(struct sockaddr*)&cli_addr,
&clilen);
if (0 > client_fd)
{
fprintf(stderr,
"Error accepting connection. [%s]\n",
strerror(errno));
continue;
}
err = sem_trywait(&(g_serv.client_count_sem));
if (0 > err)
{
fprintf(stderr,
"Max connections reached. [%s]\n",
strerror(errno));
notify_client_max_connections(client_fd);
close(client_fd);
client_fd = 0;
continue;
}
printf("A client has connected.\n");
char byte[2] = "0";
err = send(client_fd, byte, 1, 0);
// Set up client FD in global position and wake up a thread to grab it
//
pthread_mutex_lock(&(g_serv.new_connection_fd_lock));
g_serv.new_connection_fd = client_fd;
if (0 != g_serv.new_connection_fd)
{
pthread_cond_signal(&(g_serv.new_connection));
}
pthread_mutex_unlock(&(g_serv.new_connection_fd_lock));
}
This block is the thread handling function:
void* thread_handler(void* args)
{
serv_t* p_serv = (serv_t*)args;
bool thread_client_connected;
int thread_client_fd;
while(p_serv->b_running)
{
pthread_mutex_lock(&(p_serv->new_connection_fd_lock));
while (0 == p_serv->new_connection_fd && p_serv->b_running)
{
pthread_cond_wait(&(p_serv->new_connection),
&(p_serv->new_connection_fd_lock));
}
thread_client_fd = p_serv->new_connection_fd;
p_serv->new_connection_fd = 0;
pthread_mutex_unlock(&(p_serv->new_connection_fd_lock));
// In the case of a pthread cond broadcast for exiting the server.
//
if (0 == thread_client_fd)
{
continue;
}
thread_client_connected = true;
while (thread_client_connected)
{
thread_client_connected = handle_client(thread_client_fd);
}
close(thread_client_fd);
thread_client_fd = 0;
sem_post(&(p_serv->client_count_sem));
}
return NULL;
} /* thread_handler */
Just for data reference here is my serv_t struct:
typedef struct serv_t {
bool b_running;
int max_connections;
int serv_listener_fd;
sem_t client_count_sem;
pthread_mutex_t new_connection_fd_lock;
pthread_cond_t new_connection;
int new_connection_fd;
pthread_t* p_thread_ids;
} serv_t;
Basically, if I run netcat or a client program I have against it with multiple instances via a bash command to "background" the application, some of these instances get stuck. I have it redirecting the output to a file, but what's happening is that particular instance of the client/netcat is just getting stuck after the accept call.
More specifically, if I run my program with two threads, one instance of a program gets stuck and no subsequent copies get stuck, even running 6500 instances against the server.
If I run it with ten threads, as many as 8 or 9 instances get stuck, but the threads still function properly within the server.
EDIT:
Client code I refer to, starting from the server letting the client know that the server is ready to receive data:
char buff[2] = { 0 };
err = recv(client_socket_fd, buff, 1, 0);
if ('0' != buff[0] && 1 != err)
{
fprintf(stderr,
"Server handshake error. [%s]\n",
strerror(errno));
close(client_socket_fd);
return EXIT_FAILURE;
}
if (NULL != p_infix_string)
{
if (MAX_BUFFER_SIZE < strlen(p_infix_string))
{
fprintf(stderr,
"Infix string is over 100 characters long.\n");
return EXIT_FAILURE;
}
errno = 0;
char* p_postfix = infix_to_postfix(p_infix_string);
if (EINVAL == errno || NULL == p_postfix)
{
fprintf(stderr, "Error converting provided string.\n");
}
bool success = send_postfix(p_postfix, client_socket_fd);
free(p_postfix);
if (false == success)
{
fprintf(stderr,
"An error occured while sending the equation to the server.\n");
close(client_socket_fd);
return EXIT_FAILURE;
}
}
The client is getting stuck at the receive call here:
bool send_postfix(char* p_postfix, int client_socket_fd)
{
if (NULL == p_postfix)
{
fprintf(stderr, "No postfix string provided to send to server.\n");
return false;
}
printf("Sending postfix to server\n");
int err = send(client_socket_fd,
p_postfix,
strnlen(p_postfix, MAX_BUFFER_SIZE),
0);
if(strnlen(p_postfix, MAX_BUFFER_SIZE) > err)
{
fprintf(stderr,
"Unable to send message to server. [%s]\n",
strerror(errno));
return false;
}
char response[MAX_BUFFER_SIZE] = { 0 };
printf("Waiting for receive\n");
err = recv(client_socket_fd, &response, MAX_BUFFER_SIZE, 0);
if (0 == err)
{
fprintf(stderr,
"Connection to server lost. [%s]\n",
strerror(errno));
return false;
}
else if (0 > err)
{
fprintf(stderr,
"Unable to receive message on socket. [%s]\n",
strerror(errno));
return false;
}
printf("Server responded with: \n%s\n", response);
return true;
} /* send_postfix */
EDIT: https://github.com/TheStaplergun/Problem-Code
I uploaded the code to this repo and removed the need for the extraneous files I use and filled them with placeholders.
You can recreate this problem using the server with the command ./postfix_server -p 8888 -n 2 and the client issue in another terminal with for i in {1..4}; do ./postfix_client -i 127.0.0.1 -p 8888 -e "3 + $i" &> $i.txt & done
The output of each client will be forcefully flushed because of the setbuf at the top of client. Run it, see if any programs hang, if not run that command again. Just type PS and see if one of them is hanging, and look at the resulting text file. You will see it is stuck at the receive call.
If you sigint the server (CTRL + C), the client that was stuck will close with a Connection reset by peer response from the server, so the server still does have that file descriptor locked up somewhere.
I believe a race condition is happening somehow, because it only happens randomly.
A curious thing is it only happens ONCE PER SERVER INSTANCE.
If I kill that hung instance and proceed to do it again 10000 times it never does another hang until the server is reset.
For some reason, even with the following code flow inside of the
server, some clients "Fall through the cracks" and get stuck in limbo.
(They never get handled by the server so they just hang after
accepting the connection)
There may be other issues, but the first one I see is that main loop does not ensure that a new connection is actually picked up by any handler thread before it tries to hand off the next connection. Even if there are handler threads already blocked on the CV when a new connection is accepted, it is possible for the main server thread to signal the CV, loop back around, accept another connection, reacquire the mutex, and overwrite the new-connection FD before any handler thread picks up the previous one. The chances of that increase if you have more threads than cores.
Note that that will also interfere with your semaphore-based counting of available handlers -- you decrement the semaphore for every semaphore accepted, but you increment it again only for those that are successfully handled.
There are various ways that you could make the main server thread wait for the new connection to be picked up by a handler. One group would involve the server waiting on a CV itself, and relying on a handler to signal it after picking up the connection. Another, perhaps simpler, approach would involve using a semaphore to similar effect. But I would suggest instead not waiting, but instead creating a thread-safe queue for available connections, so that the server doesn't have to wait. That would even allow for queueing more connections than presently available handlers, if that would be useful to you.
I wrote in C a server - client chatroom.
The server creates a new pthread for every new connection to a client, this pthread waits for a message to receive, and sends this message to all the other clients (using a array of all the file descriptors). If a client wants to quit he informs the server and he will terminate the pthread and delete the file descriptor from the array
This works fine !, but:
if a client disconnects unexpected, by closing the terminal for example, the server won't delete the file descriptor from the array and when an other client wants to send a message i have an error because the pthread tries to send the message to a fd which isn't a connection any more
Now my question:
How can in test if the file descriptor of a client's socket is still active before i send a message ?
the part of my code (from the pthread):
for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
if (fd_array[i] != fd){ // <- i want to test the fd here
if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
perror("Serveur: send");
}
}
}
Check the return value of the recv().
If the user terminated abnormally then return value should be zero 0.
Based on that you can close fd easily.
if(recv(fd,buffer,length,flag) == 0)
close(fd);
There is no standalone api to check whether socket is closed. Just try to send data to that socket.
send will return -1 if you write to a closed socket. and errno will be set to appropriately. You may got EBADF or ECONNRESET i guess. Check (Check connection open or closed ?(in C in Linux)) and (How to find out if a socket is closed)
for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
if (fd_array[i] != fd){ // <- i want to test the fd here
if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
//perror("Serveur: send");
// something wrong, check errno to see more detail
// you need to include <errno.h> to use errno
close(fd_array[i]);
fd_array[i] = -1;// or something you define as not open
}
}
}
I have the following situation. My server receives data from remote server (fd_server) and forwards it to the client (fd_client). I'm using edge triggered epoll so I can handle multiple clients and multiple server conncetions.
Procedure:
client connects to the server.
my server connects to the remote server and requests data.
remote server responds and my server forwards data to the client.
Details:
After my server connects to the remote server the fd_server is added to epoll control with EPOLLIN flag. Server waits for events.
When epoll_wait return the fd_server as readable I go in the following loop displayed bellow.
After some read/writes my sctp_sendmsg return EAGAIN, which means sctp send buffer is full. How should I handle this situation without loosing the data I have already read from the fd_server socket?
IS there a way of knowing before hand, how much data can I send, so I only read the right amount?
while(1){
N = recv(fd_server,buf, sizeof buf,0);
if (N == -1){
/* If errno == EAGAIN, that means we have read all
data. So go back to the main loop. */
if (errno != EAGAIN){
perror ("tcp_recv error");
}
break;
}
if(N == 0){
/* End of file. The remote has closed the
connection. */
close(fd_server);
break;
}
pos = 0;
while(pos < N){
got = sctp_sendmsg(fd_client, &buf[pos], N-pos, to, tolen, 0, 0, stream, 0, 0);
if(got<=0){
if (errno == EAGAIN){
//what to do?
}else{
perror("tcp to sctp send error");
}
}
else{
pos += got;}
}
}
After some read/writes my sctp_sendmsg return EAGAIN, which means sctp send buffer is full. How should I handle this situation without losing the data I have already read from the fd_server socket?
You need to keep some sort of "context" (data structure) for each fd_client socket. For each new client socket that gets connected to your server, create an instance of a "connection state" struct and store it in a hash table. This will be something like the following:
struct ConnectionState
{
int fd_client; // socket
uint8_t buffer[MAX_CHUNK_SIZE]; // protocol buffer for this connection
int buffer_length; // how many bytes received into this buffer
int pos; // how many bytes transmitted back out on fd_client from "buffer"
int has_data; // boolean to indicate protocol state (1 if there's still data in buffer to send)
};
If you can't send everything at once, toggle the fd_client socket from EPOLLIN to EPOLLOUT in your epoll mode. Change "has_data" to true in the ConnectionState structure. Then go back to waiting for socket events. When you are able to send again, you look at your ConnectionState struct for that socket to decide if you still need to keep sending or receive a new buffer.
Be careful with edge triggered sockets. When you do transition from EPOLLOUT back to EPOLLIN, you need to go ahead and recv() again just to make sure you don't lose any data. (Similarly for entering the send state, try an initial send).
This time I code a chat server and client. The idea is this.
The server uses the select method for with a readfd(FD_SET) to seek which of the clients connected on it have something to send. If it founds something it send it to the rest of clients.
Here is the select function on server and a part of server's code.
SelectResults = select(maxDescriptor+1,&BackUpfdread,NULL,NULL,&time);
I use the select function in client too, to make it seek for incoming and outcoming messages.(these that server sends from other clients and these that this client want to send).
Well, the client in the select function has a fdread and fdwrite (FD_SET).
Here is the part of the code that client has for the connection and for the chat.
The problem is that if i connect two clients on the server message transfer isn't concurrent and that means that clients cannot chat correctly.
Finally i thought to use threads in server. One thread for waiting to receive and one for sending to the clients, but i want to hear and your opinion.
In the client you don't really need that loop from 0 to maxDescriptor. Just check if ConnectSocket is set. Something like this:
// Main loop starts here
for(; ;)
{
memset(SentBuff, 0, sizeof(SentBuff));
printf("Write: ");
gets_s(SentBuff, sizeof(SentBuff));
// Copy the fdread into BackUpfdread and fdwrite to BackUpfdwrite.
BackUpfdread = fdread;
BackUpfdwrite = fdwrite;
SelectResults = select(maxDescriptor+1,&BackUpfdread,&BackUpfdwrite,NULL,&timer);
if(SelectResults == -1)
{
perror("Client-select() error!\n");
exit(1);
}
if (FD_ISSET(ConnectSocket, &BackUpfdread))
{
RecvBytes = recv(ConnectSocket, RecvBuff, sizeof(RecvBuff), 0);
if(RecvBytes > 0)
{
printf("%s\n",RecvBuff);
// Cleaning the Receive Buffer
memset(RecvBuff,0,sizeof(RecvBuff));
}
}
if (FD_ISSET(ConnectSocket, &BackUpfdwrite))
{
SentBytes = send(ConnectSocket, SentBuff,sizeof(SentBuff),0);
// Cleaning the Sent Buffer
memset(SentBuff,0,sizeof(SentBuff));
}
} // Main loop ends here
Also don't forget to check for errors from send and recv. Especially recv is important, as it's the call that will tell you the server has disconnected.
Edit: Another important thing to note, is that the socket may be writeable always, so add a check if there is something to write before you check if the socket is writeable.
I have a TCP connection. Server just reads data from the client. Now, if the connection is lost, the client will get an error while writing the data to the pipe (broken pipe), but the server still listens on that pipe. Is there any way I can find if the connection is UP or NOT?
You could call getsockopt just like the following:
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
To test if the socket is up:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
}
The only way to reliably detect if a socket is still connected is to periodically try to send data. Its usually more convenient to define an application level 'ping' packet that the clients ignore, but if the protocol is already specced out without such a capability you should be able to configure tcp sockets to do this by setting the SO_KEEPALIVE socket option. I've linked to the winsock documentation, but the same functionality should be available on all BSD-like socket stacks.
TCP keepalive socket option (SO_KEEPALIVE) would help in this scenario and close server socket in case of connection loss.
There is an easy way to check socket connection state via poll call. First, you need to poll socket, whether it has POLLIN event.
If socket is not closed and there is data to read then read will return more than zero.
If there is no new data on socket, then POLLIN will be set to 0 in revents
If socket is closed then POLLIN flag will be set to one and read will return 0.
Here is small code snippet:
int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}
Very simple, as pictured in the recv.
To check that you will want to read 1 byte from the socket with MSG_PEEK and MSG_DONT_WAIT. This will not dequeue data (PEEK) and the operation is nonblocking (DONT_WAIT)
while (recv(client->socket,NULL,1, MSG_PEEK | MSG_DONTWAIT) != 0) {
sleep(rand() % 2); // Sleep for a bit to avoid spam
fflush(stdin);
printf("I am alive: %d\n", socket);
}
// When the client has disconnected, this line will execute
printf("Client %d went away :(\n", client->socket);
Found the example here.
I had a similar problem. I wanted to know whether the server is connected to client or the client is connected to server. In such circumstances the return value of the recv function can come in handy. If the socket is not connected it will return 0 bytes. Thus using this I broke the loop and did not have to use any extra threads of functions. You might also use this same if experts feel this is the correct method.
get sock opt may be somewhat useful, however, another way would to have a signal handler installed for SIGPIPE. Basically whenever you the socket connection breaks, the kernel will send a SIGPIPE signal to the process and then you can do the needful. But this still does not provide the solution for knowing the status of the connection. hope this helps.
You should try to use: getpeername function.
now when the connection is down you will get in errno:
ENOTCONN - The socket is not connected.
which means for you DOWN.
else (if no other failures) there the return code will 0 --> which means UP.
resources:
man page: http://man7.org/linux/man-pages/man2/getpeername.2.html
On Windows you can query the precise state of any port on any network-adapter using:
GetExtendedTcpTable
You can filter it to only those related to your process, etc and do as you wish periodically monitoring as needed. This is "an alternative" approach.
You could also duplicate the socket handle and set up an IOCP/Overlapped i/o wait on the socket and monitor it that way as well.
#include <sys/socket.h>
#include <poll.h>
...
int client = accept(sock_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
pollfd pfd = {client, POLLERR, 0}; // monitor errors occurring on client fd
...
while(true)
{
...
if(not check_connection(pfd, 5))
{
close(client);
close(sock[1]);
if(reconnect(HOST, PORT, reconnect_function))
printf("Reconnected.\n");
pfd = {client, POLLERR, 0};
}
...
}
...
bool check_connection(pollfd &pfd, int poll_timeout)
{
poll(&pfd, 1, poll_timeout);
return not (pfd.revents & POLLERR);
}
you can use SS_ISCONNECTED macro in getsockopt() function.
SS_ISCONNECTED is define in socketvar.h.
For BSD sockets I'd check out Beej's guide. When recv returns 0 you know the other side disconnected.
Now you might actually be asking, what is the easiest way to detect the other side disconnecting? One way of doing it is to have a thread always doing a recv. That thread will be able to instantly tell when the client disconnects.