test_ncbi_dsock.c

来自「ncbi源码」· C语言 代码 · 共 433 行

C
433
字号
/* * =========================================================================== * PRODUCTION $Log: test_ncbi_dsock.c,v $ * PRODUCTION Revision 1000.1  2004/02/12 21:56:23  gouriano * PRODUCTION PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14 * PRODUCTION * =========================================================================== *//*  $Id: test_ncbi_dsock.c,v 1000.1 2004/02/12 21:56:23 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Anton Lavrentiev * * File Description: *   Test suite for datagram socket API * */#include "../ncbi_ansi_ext.h"#include "../ncbi_priv.h"               /* CORE logging facilities */#include <connect/ncbi_connutil.h>#include <connect/ncbi_socket.h>#include <errno.h>#include <stdlib.h>#include <time.h>#ifdef NCBI_OS_UNIX#  include <unistd.h>#endif /*NCBI_OS_UNIX*//* This header must go last */#include "test_assert.h"#if defined(NCBI_OS_BSD) || defined(NCBI_OS_OSF1) || defined(NCBI_OS_DARWIN)   /* FreeBSD has this limit :-/ Source: `sysctl net.inet.udp.maxdgram` */   /* For OSF1 (and FreeBSD) see also: /usr/include/netinet/udp_var.h   */#  define MAX_DGRAM_SIZE (9*1024)#elif defined(NCBI_OS_IRIX)   /* This has been found experimentally on IRIX64 6.5 04101931 IP25 */#  define MAX_DGRAM_SIZE (60*1024)#elif defined(NCBI_OS_LINUX)/* Larger sizes do not seem to work everywhere */#  define MAX_DGRAM_SIZE 65000#else   /* This is the maximal datagram size defined by the UDP standard */#  define MAX_DGRAM_SIZE 65535#endif#define DEFAULT_PORT 55555static int s_Usage(const char* prog){    CORE_LOGF(eLOG_Error, ("Usage:\n%s {client|server} [port [seed]]", prog));    return 1;}static int s_Server(int x_port){    char           addr[32];    char*          buf;    SOCK           server;    EIO_Status     status;    STimeout       timeout;    unsigned int   peeraddr;    unsigned short peerport, port;    size_t         msglen, n, len;    char           minibuf[255];    if (x_port <= 0) {        CORE_LOG(eLOG_Error, "[Server]  Port wrongly specified");        return 1;    }    port = (unsigned short) x_port;    CORE_LOGF(eLOG_Note, ("[Server]  Opening DSOCK on port %hu", port));    if ((status = DSOCK_Create(&server)) != eIO_Success) {        CORE_LOGF(eLOG_Error, ("[Server]  Error creating DSOCK: %s",                               IO_StatusStr(status)));        return 1;    }    if ((status = DSOCK_Bind(server, port)) != eIO_Success) {        CORE_LOGF(eLOG_Error, ("[Server]  Error binding DSOCK to port %hu: %s",                               port, IO_StatusStr(status)));        return 1;    }    for (;;) {        if ((status = DSOCK_WaitMsg(server, 0/*infinite*/)) != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Server]  Error waiting on DSOCK: %s",                                   IO_StatusStr(status)));            break;        }        timeout.sec  = 0;        timeout.usec = 0;        if ((status = SOCK_SetTimeout(server, eIO_Read, &timeout))            != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Server]  Error setting zero read tmo: %s",                                   IO_StatusStr(status)));            break;        }        len = (size_t)(((double) rand()/(double) RAND_MAX)*sizeof(minibuf));        if ((status = DSOCK_RecvMsg(server, minibuf, len, 0, &msglen,                                    &peeraddr, &peerport)) != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Server]  Error reading from DSOCK: %s",                                   IO_StatusStr(status)));            continue;        }        if (len > msglen)            len = msglen;        if (SOCK_ntoa(peeraddr, addr, sizeof(addr)) != 0)            strcpy(addr, "<unknown>");        CORE_LOGF(eLOG_Note, ("[Server]  Message received from %s:%hu, "                              "%lu bytes",                              addr, peerport, (unsigned long) msglen));        if (!(buf = (char*) malloc(msglen ? msglen : 1))) {            CORE_LOG_ERRNO(eLOG_Error, errno,"[Server]  Cannot alloc msg buf");            break;        }        if (len)            memcpy(buf, minibuf, len);        while (len < msglen) {            n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);            if ((status = SOCK_Read(server, buf + len, n, &n, eIO_ReadPlain))                != eIO_Success) {                CORE_LOGF(eLOG_Error,("[Server]  Error reading msg @ byte %lu:"                                      " %s", (unsigned long) len,                                      IO_StatusStr(status)));                free(buf);                continue;            }            len += n;        }        assert(SOCK_Read(server, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);        CORE_LOG(eLOG_Note, "[Server]  Bouncing the message to sender");        timeout.sec  = 1;        timeout.usec = 0;        if ((status = SOCK_SetTimeout(server, eIO_Write, &timeout))            != eIO_Success){            CORE_LOGF(eLOG_Error, ("[Server]  Error setting write tmo: %s",                                   IO_StatusStr(status)));            break;        }        for (len = 0; len < msglen; len += n) {            n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);            if ((status = SOCK_Write(server, buf + len, n, &n, eIO_WritePlain))                != eIO_Success) {                CORE_LOGF(eLOG_Error,("[Server]  Error writing msg @ byte %lu:"                                      " %s", (unsigned long) len,                                      IO_StatusStr(status)));                break;            }        }        free(buf);        if ((status = DSOCK_SendMsg(server, addr, peerport, "--Reply--", 9))            != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Server]  Error sending to DSOCK: %s",                                   IO_StatusStr(status)));            /*continue*/;        }    }    /* On errors control reaches here */    if ((status = SOCK_Close(server)) != eIO_Success) {        CORE_LOGF(eLOG_Error, ("[Server]  Error closing DSOCK: %s",                               IO_StatusStr(status)));    }    return 1;}static int s_Client(int x_port, unsigned int max_try){    size_t         msglen, n;    STimeout       timeout;    EIO_Status     status;    SOCK           client;    unsigned short port;    char*          buf;    unsigned long  id;    unsigned int   m;    if (x_port <= 0) {        CORE_LOG(eLOG_Error, "[Client]  Port wrongly specified");        return 1;    }     port = (unsigned short) x_port;    CORE_LOGF(eLOG_Note, ("[Client]  Opening DSOCK on port %hu", port));    if ((status = DSOCK_Create(&client)) != eIO_Success) {        CORE_LOGF(eLOG_Error, ("[Client]  Error creating DSOCK: %s",                               IO_StatusStr(status)));        return 1;    }    msglen = (size_t)(((double)rand()/(double)RAND_MAX)*(MAX_DGRAM_SIZE - 10));    if (msglen < sizeof(time_t))        msglen = sizeof(time_t);    CORE_LOGF(eLOG_Note, ("[Client]  Generating a message %lu bytes long",                          (unsigned long) msglen));    if (!(buf = (char*) malloc(2*msglen + 9))) {        CORE_LOG_ERRNO(eLOG_Error, errno, "[Client]  Cannot alloc msg buf");        return 1;    }    for (n = sizeof(unsigned long); n < msglen; n++)        buf[n] = rand() % 0xFF;    id = (unsigned long) time(0);    for (m = 1; m <= max_try; m++) {        unsigned long tmp;        if (m != 1)            CORE_LOGF(eLOG_Note, ("[Client]  Attempt #%u", (unsigned int) m));        id++;        *((unsigned long*) buf) = SOCK_htonl((unsigned long) id);        if ((status = DSOCK_SendMsg(client, "127.0.0.1", port, buf, msglen))            != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Client]  Error sending to DSOCK: %s",                                   IO_StatusStr(status)));            return 1;        }        timeout.sec  = 1;        timeout.usec = 0;        if ((status = SOCK_SetTimeout(client, eIO_Read, &timeout))            != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Client]  Error setting read timeout: %s",                                   IO_StatusStr(status)));            return 1;        }    again:        if ((status = DSOCK_RecvMsg(client, &buf[msglen], msglen+9,0, &n, 0,0))            != eIO_Success) {            CORE_LOGF(eLOG_Error, ("[Client]  Error reading from DSOCK: %s",                                   IO_StatusStr(status)));            continue;        }        if (n != msglen + 9) {            CORE_LOGF(eLOG_Error, ("[Client]  Received message of wrong size: "                                   "%lu", (unsigned long) n));            return 1;        }        memcpy(&tmp, &buf[msglen], sizeof(tmp));        if (SOCK_ntohl(tmp) != id) {            m++;            CORE_LOGF(m < max_try ? eLOG_Warning : eLOG_Error,                      ("[Client]  Stale message received%s",                       m <= max_try ? ", reattempting to fetch" : ""));            if (m <= max_try)                goto again;            break;        }        CORE_LOGF(eLOG_Note, ("[Client]  Received the message back, %lu bytes",                              (unsigned long) n));        assert(SOCK_Read(client, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);        break;    }    if (m > max_try)        return 1;    for (n = sizeof(unsigned long); n < msglen; n++) {        if (buf[n] != buf[msglen + n])            break;    }    if (n < msglen) {        CORE_LOGF(eLOG_Error, ("[Client]  Bounced message corrupted, off=%lu",                               (unsigned long) n));        return 1;    }    if (strncmp(&buf[msglen*2], "--Reply--", 9) != 0) {        CORE_LOGF(eLOG_Error, ("[Client]  No signature in the message: %.9s",                               &buf[msglen*2]));        return 1;    }    free(buf);    if ((status = SOCK_Close(client)) != eIO_Success) {        CORE_LOGF(eLOG_Error, ("[Client]  Error closing DSOCK: %s",                               IO_StatusStr(status)));        return 1;    }    CORE_LOG(eLOG_Note, "[Client]  Completed successfully");    return 0;}int main(int argc, const char* argv[]){    unsigned long seed;    unsigned int  max_try = DEF_CONN_MAX_TRY;    const char*   env = getenv("CONN_DEBUG_PRINTOUT");    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |                           fLOG_OmitNoteLevel | fLOG_DateTime);    CORE_SetLOGFILE(stderr, 0/*false*/);    if (argc < 2 || argc > 4)        return s_Usage(argv[0]);    if (argc <= 3) {#ifdef NCBI_OS_UNIX        seed = (unsigned long) time(0) + (unsigned long) getpid();#else        seed = (unsigned long) time(0);#endif /*NCBI_OS_UNIX*/    } else        sscanf(argv[3], "%lu", &seed);    CORE_LOGF(eLOG_Note, ("Random SEED = %lu", seed));    srand(seed);    if (env && (strcasecmp(env, "1") == 0     ||                strcasecmp(env, "yes") == 0   ||                strcasecmp(env, "true") == 0  ||                strcasecmp(env, "some") == 0  ||                strcasecmp(env, "data") == 0)) {        SOCK_SetDataLoggingAPI(eOn);    }    if (!(env = getenv("CONN_MAX_TRY"))  ||  !(max_try = atoi(env)))        max_try = DEF_CONN_MAX_TRY;    if (strcasecmp(argv[1], "client") == 0)        return s_Client(argv[2] ? atoi(argv[2]) : DEFAULT_PORT, max_try);    if (strcasecmp(argv[1], "server") == 0)        return s_Server(argv[2] ? atoi(argv[2]) : DEFAULT_PORT);    return s_Usage(argv[0]);}/* * -------------------------------------------------------------------------- * $Log: test_ncbi_dsock.c,v $ * Revision 1000.1  2004/02/12 21:56:23  gouriano * PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14 * * Revision 6.14  2003/12/11 15:34:29  lavr * Lower maximal datagram size for Linux - 65535 didn't seem to work everywhere * * Revision 6.13  2003/12/10 17:24:16  lavr * Reattempt to send/receive a datagram on I/O errors in client * * Revision 6.12  2003/10/27 19:00:32  lavr * Limit datagram size for Darwin (which is BSD based) * * Revision 6.11  2003/05/29 18:03:06  lavr * Changed one client's message * * Revision 6.10  2003/05/14 03:58:43  lavr * Match changes in respective APIs of the tests * * Revision 6.9  2003/04/30 17:04:01  lavr * Conformance to slightly modified datagram socket API * * Revision 6.8  2003/03/25 15:07:21  lavr * Protect macros' values by enclosing in parentheses * * Revision 6.7  2003/03/25 15:04:13  lavr * Add IRIX-specific datagram size limit (60K) * * Revision 6.6  2003/02/28 14:46:36  lavr * Explicit casts for malloc()'ed memory * * Revision 6.5  2003/02/14 15:41:26  lavr * Limit packet size on OSF1, too * * Revision 6.4  2003/02/06 04:34:28  lavr * Do not exceed maximal dgram size on BSD; trickier readout in s_Server() * * Revision 6.3  2003/02/04 22:04:47  lavr * Protection from truncation to 0 in double->int conversion * * Revision 6.2  2003/01/17 01:26:44  lavr * Test improved/extended * * Revision 6.1  2003/01/16 16:33:06  lavr * Initial revision * * ========================================================================== */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?