2of1
half a nibble of another

Home
Projects
About
Jun

08

accept()ing multiple tcp connections

Filed Under (C, Coding, Networking) by 2of1 on 08-06-2010

The best way I’ve found of handling multiple tcp connections on the same socket is to use a poll file device with the listen()ing socket itself as the first pfd.

The example below is based on a i5/OS example available from IBM at http://publib.boulder.ibm.com/infocenter/iseries/v6r1m0/index.jsp?topic=/rzab6/example.htm.
I’ve made some minor changes to how flags are set to allow the example below to work on Linux/Win/BSD.

(Please note the lack of error checking in the code below. You should obviously have some in your application.)

#include ...
#include <poll.h>
#include <fcntl.h>
 
int listen_sd, cli_len, npfds = 1, port = 12345, max_connections = 5, one = 1;
struct sockaddr_in srv;
struct pollfd pfds[100];
 
memset(pfds, 0, sizeof(pfds));
memset(&srv, 0, sizeof(srv);
 
listen_sd = socket(AF_INET, SOCK_STREAM, 0);    // set up socket
setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));  // allow for port reuse
 
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = INADDR_ANY;
srv.sin_port = htons(port);
 
fcntl(listen_sd, FSETFL, O_NONBLOCK);    // make sure socket doesn't block
 
bind(listen_sd, (struct sockaddr *)&srv, sizeof(srv));    // bind
listen(listen_sd, max_connections);     // listens for a max of 5 connections
 
pfds[0].fd = listen_fd;        // set up the first pfd to be the listen()ing socket
pfds[0].events = POLLIN;  // trigger when POLLIN event
 
while (1) {
    if (poll(pfds, npfds, -1) > 0) {    // there's an event waiting
    int i, j = npfds;
    for(i = 0; i < j; i++) {    // process each fd
        if (pfds[i].revents == 0) continue;    // this fd has nothing to process, so move to next
 
        if (pfds[i].fd == listen_sd) {    // event has been received on the listening socket
            int fd;
            do {
                int flags;
                fd = accept(listen_sd, NULL, NULL);
 
                flags = fcntl(fd, F_GETFL, NULL) | ~O_NONBLOCK;
                fcntl(fd, F_SETFL, flags);    // make sure fd doesn't block
 
                // set up the new pfd
                pfds[npfds].fd = fd;
                pfds[npfds].events = POLLIN;
                npfds++;
            } while (fd != -1);
        } else {   // there is input waiting on the current connection fd
            unsigned char buf[1000];
            if (recv(pfds[i].fd, buf, 1000) > 0) {
                // process data
            } else {    // connection has been closed
                close(pfds[i].fd);
                remove_pfd_from_array(pfds, &npfds, i);    // make sure pfd is no longer polled
            }
        }
    }
}

The remove_pfd_from_array() removes the disconnected fd from the array. There are better ways of doing this, but a dirty implementation looks something like this:

void remove_pfd_from_array(struct pollfd *pfds, int *npfds, int fd)
{
    int i;
    for (i = 0; i < *npfds - 1; i++)
        pfds[i] = pfds[i + 1];
    memset(pfds + i, 0, sizeof(struct pollfd));
    (*npfds)--;
}
No Comments
Read More

Leave a Reply

  • Recent Posts

    • ARM long branch
    • Mini-Namco #3: (Almost) Finished
    • Mini-Namco #2: Unit construction
    • Mini-Namco #1: Design
    • Simple C hashtable code
  • Archives

    • January 2012
    • September 2011
    • August 2011
    • July 2011
    • May 2011
    • March 2011
    • February 2011
    • January 2011
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
  • GitHub

    • code
    • d2d1headers
    • locateme
    • findjerusalem
    • seg7
    • userspace-krb
    • libgmail
    • preloader
    • linhook
  • qrcode

  • Site Search

  • Categories

    • Apps (7)
      • Preloader (1)
      • Symbian S60 (1)
      • VLC (4)
      • Wordpress (1)
    • Coding (28)
      • Assembly (1)
        • ARM (1)
      • C (12)
      • Compilers (5)
      • Direct2D API (4)
      • Linux kernel (2)
      • Networking (4)
      • Python (1)
      • Sqlite (1)
      • Version control (5)
        • Git (5)
    • Hacking (4)
      • Code injection (1)
      • Reverse engineering (3)
    • Hardware (4)
      • Arduino (1)
      • PCBs (3)
    • Linux (21)
      • Bash (1)
      • Tips & tricks (13)
      • Virtualization (1)
      • VNC (2)
      • Xmonad (1)
    • Open source (30)
    • Other stuffs (3)
    • Social (3)
      • DC9723 (2)
  • OctoFinderProgramming Blogs - Blog Catalog Blog Directory

    Locations of visitors to this page

© 2of1.