Polling TCP connections in C
<p>I'm working on a school task where i have to make a server that gets TCP connections. Those connections then pass data. I use poll() to see if there is a new connection request or if there is incoming data from an existing connection. It's used with the loop back address (127.0.0.1).</p>

<p>It works fine when i have 1 connection, but when i open a second one, it stops polling and wait for the data from the new connection. 
The strange thing is, that if i open a third connection, it does give the data of that third connection as well, but still no polling, just waiting.</p>

<p>I read a lot about it and i'm stuck on it for a while.</p>

<p>I wrote the server-code in the connmgr.c (with a lot of printf's for finding my mistake). I'll explain below:</p>

<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;inttypes.h&gt;
#include &lt;assert.h&gt;

#include &lt;unistd.h&gt;
#include &lt;signal.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;syslog.h&gt;
#include &lt;poll.h&gt;

#include "connmgr.h"

#define _GNU_SOURCE

static FILE * write_file;
struct pollfd *poll_list;
int serversd;
int conn_counter = 0;

int dplist_errno;

dplist_t * list = NULL;
list_node_t * dummy = NULL;


void * element_copy(void *element);
void element_free(void **element);
int element_compare(void *x, void *y);


void add_poll(struct pollfd * polllist, tcpsock_t *client, tcpsock_t *server){
conn_counter++;
polllist = realloc(polllist,sizeof(struct pollfd)*conn_counter+1);
int clientsd;
tcp_get_sd(client, &amp;clientsd);
polllist[conn_counter].fd= clientsd;
//printf("fd in add_poll = %d \n",clientsd);
polllist[conn_counter].events = POLLIN;
}
    int stop = 0;
    tcpsock_t *server, *client;

void connmgr_listen(int port_number){

    sensor_data_t data;
dummy = malloc(sizeof(list_node_t));

write_file = fopen("sensor_data_recv", "w");

poll_list = malloc(sizeof(struct pollfd));
list = dpl_create(&amp;element_copy, &amp;element_free, &amp;element_compare);

if(tcp_passive_open(&amp;server,port_number)!=TCP_NO_ERROR)exit(EXIT_FAILURE);
tcp_get_sd(server, &amp;serversd);

poll_list[0].fd = serversd;
poll_list[0].events = POLLIN;

printf("server fd = %d \n",serversd);

printf("start with fd %d = %d \n", 0,poll_list[0].fd);

int bytes,result;
int test = 0;

while(1){

    test++;
    int sd;
    int return_value,i;

    return_value = poll(poll_list,conn_counter+1,TIMEOUT);

    if (return_value&gt;0){
        if(poll_list[0].revents &amp; POLLIN&gt;0){
            printf("add client\n");

            tcpsock_t * requestclient;
            if (tcp_wait_for_connection(server,&amp;requestclient)!=TCP_NO_ERROR) exit(EXIT_FAILURE);
            tcp_get_sd(requestclient, &amp;sd);
            dummy-&gt;sd = sd;
            printf("inserted sd = %d \n",sd);
            dummy-&gt;client = requestclient;
            time(&amp;(dummy-&gt;ts));
            list = dpl_insert_at_index(list, dummy, conn_counter,true);



            //printf("sd from client = %d \n", tcp_get_sd(client, &amp;sd));

            add_poll(poll_list, dummy-&gt;client, server);
            printf("conn_counter = %d \n",conn_counter);

        }

        //for (i=0; i&lt;conn_counter;i++){
        i=0;
        while(i&lt;conn_counter){
            if(poll_list[i+1].revents &amp; POLLIN&gt;0){

                printf("poll in %d \n",i+1);

                dummy = (list_node_t *) dpl_get_element_at_index(list,i);
                time(&amp;(dummy-&gt;ts));
                client = dummy-&gt;client;
                sd = dummy-&gt;sd;

                /*for(int l = 0; l&lt;conn_counter;l++){
                        printf("sensor %d \n",l);

                }*/

                bytes = sizeof(data.id);
                printf("@ line %d en i = %d \n", __LINE__,i);result = tcp_receive(client,(void *)&amp;data.id,&amp;bytes); 

                bytes = sizeof(data.value);
                printf("@ line %d \n", __LINE__);result = tcp_receive(client,(void *)&amp;data.value,&amp;bytes);

                bytes = sizeof(data.ts);
                printf("@ line %d \n", __LINE__);result = tcp_receive(client,(void *)&amp;data.ts,&amp;bytes);


                if ((result==TCP_NO_ERROR) &amp;&amp; bytes){
                printf("sensor id = %" PRIu16 " - temperature = %g - timestamp = %ld\n", data.id, data.value, (long int)data.ts);
                        }

                else{
                    if(result == TCP_CONNECTION_CLOSED){printf("peer left \n");}
                    else{"error in peerconnection \n";}
                    tcp_close(&amp;client);
                    list = dpl_remove_at_index(list, i, true);
                    }
                fflush(stdout);
            }
            if (poll_list[i+1].revents &amp; POLLHUP){
                printf("client disconnected \n");
                poll_list[conn_counter+1].fd=-1;
                poll_list[conn_counter+1].events=0;
                fflush(stdout);
            }i++;
        }       
    }
    //if(return_value&lt;0){exit(EXIT_FAILURE);}
    //if(stop == 1){break;}
    printf("end of while %d \n",test);



}
</code></pre>

<p>Once a server has started in the tcp_passive_open, it will start polling untill the return_value is high. Then it checks if the POLLIN is at [0], what means a new connection request. If not, i check all the connections in the poll_list, starting from 1 untill conn_counter. If not, i check for a POLLHUP and set the fd of that client at -1 so poll() will ignore this.</p>

<p><strong>I think it should be somewhere where i use the while-loop to check if the POLLIN is from one of the connections, because i can add connections no problem.</strong></p>

<p>the dpl_... functions are from a dubble-linked-list library i wrote myself and should work fine. They create a list, get an element at an index... The list uses 3 callback functions.</p>

<p>The tcp_... functions are functions i've got from the prof. The tcpsock.h file should give enough information:</p>

<pre><code>typedef struct tcpsock tcpsock_t;

int get_size_tcpsock();

// All functions below return TCP_NO_ERROR if no error occurs during execution

int tcp_passive_open(tcpsock_t ** socket, int port);
/* Creates a new socket and opens this socket in 'passive listening mode' (waiting for an active connection setup request) 
 * The socket is bound to port number 'port' and to any active IP interface of the system
 * The number of pending connection setup requests is set to MAX_PENDING
 * The newly created socket is returned as '*socket'
 * This function is typically called by a server
*/

int tcp_active_open(tcpsock_t ** socket, int remote_port, char * remote_ip);
/* Creates a new TCP socket and opens a TCP connection to the system with IP address 'remote_ip' on port 'remote_port'
 * The newly created socket is return as '*socket'
 * This function is typically called by a client 


int tcp_close(tcpsock_t ** socket); 
/* The socket '*socket' is closed , allocated resources are freed and '*socket' is set to NULL
 * If '*socket' is connected, a TCP shutdown on the connection is executed
 */

int tcp_wait_for_connection(tcpsock_t * socket, tcpsock_t ** new_socket); 
/* Puts the socket 'socket' in a blocking wait mode
 * Returns when an incoming TCP connection setup request is received
 * A newly created socket identifying the remote system that initiated the connection request is returned as '*new_socket'
 */

int tcp_send(tcpsock_t * socket, void * buffer, int * buf_size );
/* Initiates a send command on the socket 'socket' and tries to send the total '*buf_size' bytes of data in 'buffer' (recall that the function might block for a while)
 * The function sets '*buf_size' to the number of bytes that were really sent, which might be less than the initial '*buf_size'
 */

int tcp_receive (tcpsock_t * socket, void * buffer, int * buf_size);
/* Initiates a receive command on the socket 'socket' and tries to receive the total '*buf_size' bytes of data in 'buffer' (recall that the function might block for a while)
 * The function sets '*buf_size' to the number of bytes that were really received, which might be less than the inital '*buf_size'
 */

int tcp_get_ip_addr( tcpsock_t * socket, char ** ip_addr);
/* Set '*ip_addr' to the IP address of 'socket' (could be NULL if the IP address is not set)
 * No memory allocation is done (pointer reference assignment!), hence, no free must be called to avoid a memory leak
 */

int tcp_get_port(tcpsock_t * socket, int * port); 
/* Return the port number of the 'socket'
 */

int tcp_get_sd(tcpsock_t * socket, int * sd); 
/* Return the socket descriptor of the 'socket'
 */
</code></pre>

<p>Thank you for reading this and i hope you can help me!</p>

<p>ps, i have still some problems when i disconnect a tcp and then connect with another one, but that are problems for later :) </p>