Thread: Multi-Socket Server

  1. #1
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404

    Multi-Socket Server

    If my server is to support multiple connections on the same port, is there an elegant way to pick which socket to listen on when a connection is incoming?

    If you don't understand me here's some pseudo-code of what I mean
    Code:
    int socket[10];
    int i;
    while (still listening)
    {
        for (i = 0; i < 10; i++)
        {
            if (socket[i] == invalid_socket)
            {
                socket[i] = accept();
                break;
            }
        }
    }
    Also, I am implementing a system when I accept an http header, I limit the size of the allowed http header, to say 2048 bytes. If it's larger, I send back "Bad Request" or something similar. Once again, is there a better way of how I am doing this at the moment? This snippet takes into consideration packet fragmentation.

    Code:
    char buffer[2048];
    int numbytes = 0;
    int result;
    
    do
    {
        result = recv(sck, buffer, 2048, 0);
        if (result > 0)
        {
            if ((numbytes + result) > 2048)
            {
                //Send Bad Request
                break;
            }
            numbytes += result;
            if (last 4 bytes are \r\n\r\n)
            {
                sendtoparser(buffer, numbytes);
                break;
            }
        }
    }
    while (result > 0);
    I am looking to move a lot of my programming into C++, so it there is a way to easily manage this type of stuff, please point me to any functions or anything to make life easier!

    Thanks!

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    What do you mean by "packet fragmentation?" The normal sense of fragmentation means "IP fragmentation," something which is resolved by the TCP/IP stack automatically.

    Do you just mean integrating the complete packets into a full request?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    Exactly. I want to start processing the data until I see the typical http terminator (\r\n\r\n)

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Code:
    if (last 4 bytes are \r\n\r\n)
    That won't work with TCP. When you call recv() on a TCP socket, you will get as much data as possible to fill up your buffer. This means you can get several packets worth of data from the recv() call. You need to scan through your buffer for the \r\n\r\n bytes because it won't necessarily be at the end of the buffer.

  5. #5
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    I don't think you understand how listening sockets work.
    You have one socket listening on any particular port on any particular interface at any time. No more. When you call accept() you get an entirely new socket - you now have two sockets: a listener and a client. Something like:
    Code:
    socket_type listener;
    socket_type clients[10];
    
    // Somewhere
    client[x] = accept(listener);
    // both client[x] and listener are valid here,
    // but are two different things. listener is still
    // listening for connections, while client[x]
    // is a ready connection.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Cactus_Hugger View Post
    I don't think you understand how listening sockets work.
    I thought the same thing when I first read this.

    If my server is to support multiple connections on the same port, is there an elegant way to pick which socket to listen on when a connection is incoming?
    This does not make sense. You should only be listening on one socket (well, you could listen on more than one, but there's no point unless you thread or fork them and even then I don't think there would be much point).

    If there is a connection, it is already on a particular socket, handed out by accept() as CactusHugger mentioned. If you want to pick another socket which is also connected, that connection will be a different connection. There is no way to tell "someone is about to connect", so "when a connection is incoming" is not meaningful.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    Ok. I think I did a poor job of explaining. I have previously made servers that can support x number of connections simultaneously. What my thoughts are on this topic is that for a server, you need a listening socket, which in turn can, through functions and whatnot, create new sockets which are connections with other computers.

    Typically, when a connection is established, I create a thread dedicated for the whole connection.

    My question is whether or not there is an easier way (cleaner too) to assign these connection sockets to variables. What I do now is loop through my array of potential sockets, and whichever one is invalid, I use that one.

    Am I more clear? lol. I may be going about this entirely wrong. This would not be the first time. Self-taught has its disadvantages...

    Basically what I am asking is what is a typical flowchart of how a distinguished public application would do something along these lines. I always feel like my code is so hacky.

    Edit: Was just thinking. I think I made an important realization. Can I just pass the value of the socket along to the thread? When I get time, I'll try and test this out.
    Last edited by carrotcake1029; 04-17-2009 at 12:44 PM.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by carrotcake1029 View Post
    Typically, when a connection is established, I create a thread dedicated for the whole connection.

    My question is whether or not there is an easier way (cleaner too) to assign these connection sockets to variables. What I do now is loop through my array of potential sockets, and whichever one is invalid, I use that one.
    I'm still confused (which probably doesn't matter cause I'm unlikely to be of any help, but): if each connection gets it's own thread, why do you have to loop thru them?

    Also, a socket variable is just an int; why would you care about "reusing them"?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    typically, this is done like:
    Code:
    // pseudo code
    int main(void)
    {
        int server_socket = socket();
        listen();
        bind();
        while(running)
        {
            int new_socket = accept(server_socket);
    
            struct connection* c = malloc(); // create a struct to represent this connection
            c->socket = new_socket;
            c->thread_id = begin_thread(c);
            add_to_connection_list(c); // save all connections in a container of some kind
        }
        return 0;
    }
    
    // thread procedure
    void thread_proc(void* param)
    {
        struct connection* c = param;
    
        while(connection_active)
        {
            c.data = recv(socket);
            process_data(data);
            send(socket); // send some kind of response
        }
    
        // Since this connection is no longer active
        remove_from_connection_list(c);
    }
    Obviously the code is simplified, but you should be able to follow the logic. The connection data is stored in a structure, and there is a container of some kind that stores all these connections. You will need to synchronize access to this container since it will be accessed by multiple threads. If you are using C++ instead of C, then you can make a connection class with member functions/data instead of just using a struct.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I can't believe none of you have mentioned select. You need to run visit Beej's guide.


    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    ew. ;-) epoll(), for the win. Or, if you don't want to bother with writing the code, (and can wrap your head around it) boost::asio (and gain the cross-platformyness).
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Socket Server
    By carrotcake1029 in forum Windows Programming
    Replies: 2
    Last Post: 07-21-2008, 11:46 AM
  2. Server Architecture
    By coder8137 in forum Networking/Device Communication
    Replies: 2
    Last Post: 01-29-2008, 11:21 PM
  3. Where's the EPIPE signal?
    By marc.andrysco in forum Networking/Device Communication
    Replies: 0
    Last Post: 12-23-2006, 08:04 PM
  4. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM
  5. socket, udp,Halflife Server
    By Tolpan in forum C Programming
    Replies: 2
    Last Post: 06-21-2002, 09:02 AM