Thread: Help with unix/windows sockets.

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    1

    Help with unix/windows sockets.

    Hi all! I am writing a simple C project (multiclient UNIX&&WINDOWS echo server). I got the code to work on both UNIX and WINDOWS but can't figure out the multiclient part. Could someone give me a hint on that? Here is my code:
    Code:
    
    #ifdef _WIN32
    #include <winsock2.h>
    #define socklen_t int
    #else
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #endif
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    
    int main(int argc, char *argv []){
    
    
        unsigned int port;
        int l_socket;
        int c_socket;
    
    
        struct sockaddr_in servaddr;
        struct sockaddr_in clientaddr;
        socklen_t clientaddrlen;
    
    
        int s_len;
        int r_len;
        char buffer[1024];
        
        if (argc != 2){
            printf("USAGE: %s <port number>\n", argv[0]);
            exit(1);
        }
    
    
        port = atoi(argv[1]);
    
    
        if ((port < 1) && (port > 65535)){
            printf("Invalid port.\n");
            exit(1);
        }
    
    
    #ifdef _WIN32
        WSAStartup(MAKEWORD(2,2),&data);    
    #endif
    
    
        if ((l_socket = socket(AF_INET, SOCK_STREAM,0))< 0){
            fprintf(stderr,"Can't create listening socket.\n");
            exit(1);
        }
        
        memset(&servaddr,0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
    
    
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
        servaddr.sin_port = htons(port);
        
        if (bind (l_socket, (struct sockaddr *)&servaddr,sizeof(servaddr))<0){
            fprintf(stderr,"Can't bind listening socket.\n");
            exit(1);
        }
    
    
        if (listen(l_socket, 5) <0){
            fprintf(stderr,"listen() error.\n");
            exit(1);
        }
    
    
        for(;;){
            memset(&clientaddr,0, sizeof(clientaddr));
            memset(&buffer,0,sizeof(buffer));
    
    
            clientaddrlen = sizeof(struct sockaddr);
            if ((c_socket = accept(l_socket,
                (struct sockaddr*)&clientaddr,&clientaddrlen))<0){
                fprintf(stderr,"Error accepting connection.\n");
                exit(1);
            }
    
    
            s_len = recv(c_socket,buffer,sizeof(buffer),0);
    
    
            r_len = send(c_socket,buffer,s_len,0);
    
    
    
    
            printf("IP: %s Sent: %d Received: %d\n",inet_ntoa(clientaddr.sin_addr),
                s_len, r_len
            );
            
            close(c_socket);
        }
    
    
        return 0;
    }
    Thanks!

  2. #2
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    If you are talking about the server handling clients concurrently - you're not going to find anything particularly cross-platform - generally processes or threads are used in *nix and threads are used in windows. There's a few introductory tutorials on threads and processes on the web.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You're not clear on whether you want multiple clients sequentially or simultaneously. If it's sequentially, it's more or less wrapping what you have in a loop. If it's simultaneous, it's a bit more work.

    For starters, handling multiplexed IO varies greatly by OS. There is also no portable way to create child processes/threads. While the basic socket code is similar, everything else would be wildly different. There is no clean, portable way to do it. If you do go through with this, it will be a good learning experience. It will give you a good idea of writing cross-platform code, and how to write loosely coupled code to work with different interfaces (effectively, every solution to your multi-client issue requires dealing with an "interface" to multiplexed IO). Good, modular, loosely couple code is a sign of good design/architecture.

    Onto some specifics: I am not a Windows programmer, so I can only give some Linux advice.

    Take a read through Beej's network guide, especially section 7 where it talks about multiplexing (select/poll). There are a few other alternatives like non-blocking sockets (you would have to implement your own select/poll type loop), or you could create a child to handle each client using fork to create child processes or using pthreads to create child threads.

    select/poll are meant for multiplexed IO. I find the interface a bit of a pain, but it's good at what it does.

    I don't think your own poll/select type loop with non-blocking sockets is a good idea, except as an academic exercise.

    Using threads or child processes is a common way for a server (e.g. a web server) to handle multiple requests. This works especially well and is fairly easy when you don't need to communicate back to the parent process/main thread or share much data between processes/threads.

    One note, when you have to deal with cross-platform stuff, try not to just munge it into main or something. Wrap it up in a nice function:
    Code:
    void DoStartupStuff(void *data)  // note, in the above code, data is not declared, adjust it's type accordingly
    {
    #ifdef _WIN32
        WSAStartup(MAKEWORD(2,2), data);
    #endif
    }
    ...
    DoStartupStuff(&data);
    If you really wanted to get into well-designed, cross-platform software, you would design an interface that does everything you need, and make several implementations of that, in different modules or .c files. Then you compile and link with the appropriate ones when you build for different platforms.
    Code:
    // windows_stuff.c
    void DoStartupStuff(void *data)
    {
        WSAStartup(MAKEWORD(2, 2), data);
    }
    
    // linux_stuff.c
    void DoStartupStuff(void *data)
    {
    }
    
    // main.c
    DoStartupStuff(&data);

  4. #4
    Registered User
    Join Date
    Mar 2012
    Location
    the c - side
    Posts
    373
    Just read andurils response, and remembered that using select() can result in reasonably cross-platform code.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. help with UNIX sockets.... please
    By osubuckeye84 in forum C Programming
    Replies: 3
    Last Post: 02-15-2011, 06:50 AM
  2. Unix sockets
    By karas in forum Linux Programming
    Replies: 8
    Last Post: 10-13-2007, 12:20 AM
  3. Winsock vs Unix Sockets
    By khoxxxy in forum Networking/Device Communication
    Replies: 4
    Last Post: 08-05-2003, 05:13 AM
  4. Unix Sockets
    By prvindia in forum Linux Programming
    Replies: 5
    Last Post: 03-11-2003, 09:16 AM
  5. new to unix sockets
    By lithium in forum C Programming
    Replies: 3
    Last Post: 01-20-2003, 05:53 AM

Tags for this Thread