Bibilioteka komunikacji międzyprocesowej dla C [zamknięte]

Ktokolwiek słyszał, ktokolwiek wie!

Szukam biblioteki dla języka C abstrahującej najprostszą komunikację międzyprocesową od systemu operacyjnego (Windows, Linux) - wystarczy najprostszy wrapper na sockety. Nie cierpię API Windows'ów, a mam potrzebę skomunikować dwa procesu w stylu POSIX'owym.

Google okazało się mało pomocne w tej materii.

Porady do C++ niemile widziane. Z góry dziękuję.

Powód zamknięcia: Udzielono odpowiedzi na pytanie, poprawna odpowiedź została zaakceptowana

  • Polecam gliba . Da się zbudować pod windowsem, prosty, przetestowany, dobra dokumentacja.

  • Nie usatysfakcjonowany zasobami internetu, wynikami wyszukiwania Google... to choć zaciekawiony GLib'em, zdążyłem napisać własny wrapper na komunikację międzyprocesową na bazie BSD sockets. Wynik prezentuję poniżej.

    Kod działa pod Windows, Linux i Solaris (ten ostatni wymaga gcc -o icch icch.c -lsocket do skompilowania.

    /*****************************************************************************
     icch.c -- wrapper on sockets to implement asynchronous interprocess
               communication
    
     Copyright (c) 2010 Manveru
    
     This software is provided 'as-is', without any express or implied
     warranty. In no event will the authors be held liable for any damages
     arising from the use of this software.
    
     Permission is granted to anyone to use this software for any purpose,
     including commercial applications, and to alter it and redistribute it
     freely, subject to the following restrictions:
    
        1. The origin of this software must not be misrepresented; you must not
        claim that you wrote the original software. If you use this software
        in a product, an acknowledgment in the product documentation would be
        appreciated but is not required.
    
        2. Altered source versions must be plainly marked as such, and must not be
        misrepresented as being the original software.
    
        3. This notice may not be removed or altered from any source
        distribution.
     *****************************************************************************/
    
    #ifdef WIN32
    /* Windoze specific stuff */
    #define _WIN32_WINNT 0x0501
        #include <ws2tcpip.h>
        #include <process.h>
        #define IS_ADDR_IN_USE (WSAEADDRINUSE == (errno = WSAGetLastError()))
        #define CHECK_EWOULDBLOCK(x) (x == WSAEWOULDBLOCK)
    #else
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <fcntl.h>
        #include <netdb.h>
        #include <errno.h>
        #include <stdlib.h>
        #include <string.h>
        #define IS_ADDR_IN_USE (EADDRINUSE == errno)
        #define CHECK_EWOULDBLOCK(x) ((x == EWOULDBLOCK) || (x == ECONNREFUSED))
    #endif /* WIN32 */
    
    #include <stdio.h>
    
    static const char* icch_handshake = "-%icch_handshake%-";
    typedef enum {
        NOT_INITALIZED = 0,
        BOUND,
        CONNECTED,
        DROPPED
    } icch_internal_state_t;
    
    typedef struct {
        int sock_fd;
        icch_internal_state_t state;
        struct addrinfo* peerinfo_p;
    } icch_handler_t;
    
    static void local_perror(const char *s)
    {
    #ifdef WIN32
        int ecode = WSAGetLastError();
        if (!CHECK_EWOULDBLOCK(ecode))
        {
            char message[1024+1];
            DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM
                          | FORMAT_MESSAGE_IGNORE_INSERTS
                          | FORMAT_MESSAGE_MAX_WIDTH_MASK;
            DWORD dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
            FormatMessageA(dwFlags, NULL, ecode, dwLanguageId, (LPSTR)message, 1024, NULL);
            fprintf(stderr, "%s: %s", s, message);
    #else /* WIN32 */
        if (!CHECK_EWOULDBLOCK(errno))
        {
            perror(s);
    #endif /* WIN32 */
            exit(1);
        }
    }
    
    icch_handler_t icch_create_connection() {
        int status;
        int idx = 0;
        icch_handler_t icch_handler[2];
        struct addrinfo hints;
        struct in_addr *addr;
        socklen_t addr_size;
        unsigned long ioctlarg = 1;
    
        memset(&hints, 0, sizeof hints);   // make sure the struct is empty
        hints.ai_family = AF_UNSPEC;       // don't care IPv4 or IPv6
        hints.ai_socktype = SOCK_DGRAM; // UDP datagram sockets
        hints.ai_flags = AI_PASSIVE;       // fill in my IP for me
    
        /* prepare first address */
        if ((status = getaddrinfo("127.0.0.1", "13331", &hints, &icch_handler[0].peerinfo_p)) != 0)
        {
            fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
            exit(1);
        }
    
        /* prepare second address */ 
        if ((status = getaddrinfo("127.0.0.1", "13332", &hints, &icch_handler[1].peerinfo_p)) != 0)
        {
            fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
            exit(1);
        }
    
        while (idx < 2)
        {
            icch_handler[idx].sock_fd = socket(icch_handler[idx].peerinfo_p->ai_family,
                                               icch_handler[idx].peerinfo_p->ai_socktype,
                                               icch_handler[idx].peerinfo_p->ai_protocol);
            /* prepare non-blocking socket */
    #ifdef WIN32
            ioctlsocket(icch_handler[idx].sock_fd, FIONBIO, &ioctlarg );
    #else
            fcntl(icch_handler[idx].sock_fd, F_SETFL, O_NONBLOCK);
    #endif /* WIN32 */
    
            if(0 > bind(icch_handler[idx].sock_fd,
                    icch_handler[idx].peerinfo_p->ai_addr,
                    icch_handler[idx].peerinfo_p->ai_addrlen))
            {
                /* couple gotchas! */
                if (IS_ADDR_IN_USE)
                {
                    fprintf(stderr, "Address in use, move to next socket!\n");
                    idx++;
                    continue; /* go to process second socket */
                }
                else
                {
                    local_perror("bind");
                } /* end of if (IS_ADDR_IN_USE) */
            } 
            else /* of if (0 > bind(... */
            {
                icch_handler[idx].state = BOUND;
                /* connect - do a trick to connect to second side ! */
                fprintf(stderr, "* idx = %d; (idx + 1) % 2 = %d\n", idx, (idx + 1) % 2);
                if (0 > connect(icch_handler[idx].sock_fd,
                                icch_handler[(idx + 1) % 2].peerinfo_p->ai_addr,
                                icch_handler[(idx + 1) % 2].peerinfo_p->ai_addrlen))
                {
                    local_perror("connect");
                }
                else /* else of if (0 > connect(... */
                {
                    icch_handler[idx].state = CONNECTED;
                    break;
                } /* end of if (0 > connect(... */
            } /* end of if (0 > bind(... */
        } /* end of while (idx < 2) */
        return icch_handler[idx];
    }
    
    int icch_send(icch_handler_t *h, void* data, size_t len)
    {
        if (h->state == CONNECTED)
        {
            if (-1 == (len = send(h->sock_fd, data, len, 0)))
            {
                local_perror("send");
            }
        }
        else len = 0; /* ignore other cases */
        return len;
    }
    
    int icch_recv(icch_handler_t *h, void* data, size_t len)
    {
        if (h->state == CONNECTED)
        {
            if (-1 == (len = recv(h->sock_fd, data, len, 0)))
            {
                local_perror("recv");
                /* above exits so, clean up */
                //memset(data, 0, len);
                len = 0;
            }
        }
        else 
        {
            memset(data, 0, len);
            len = 0; /* ignore other cases */
        }
        return len;
    }
    
    #ifdef WIN32
    void win32exit(void)
    {
        WSACleanup();
    }
    #endif /* WIN32 */
    
    int main(void)
    {
        int i = 0;
        ssize_t slen = 0, rlen = 0;
        char buffer[1024] = "test123";
        icch_handler_t h = {0};
    
    #ifdef WIN32
        WSADATA wsaData;
    
        atexit(win32exit); /* Do this at the end */
    
        if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
            fprintf(stderr, "WSAStartup failed.\n");
            exit(1);
        }
    #endif /* WIN32 */
    
        h = icch_create_connection();
        printf("click\n");
        snprintf(buffer, 1024, "test pid = %d", getpid());
    
        while(i < 10)
        {
            snprintf(buffer, 1024, "test pid = %d", getpid());
            icch_send(&h, buffer, 1024);
            printf("[s]buffer = '%s'\n", buffer);
            if (0 != icch_recv(&h, buffer, 1024))
            {
                printf("[r]buffer = '%s'\n", buffer);
                i++;
            }
        }
    
        return 0;
    }
    

  • Boost Asio jest (chyba) tym, czego szukasz.

Zaloguj się, aby dodać swoją odpowiedź