⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thruput.c

📁 Netscape NSPR库源码
💻 C
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//*** File:        thruput.c** Description: Test server's throughput capability comparing various**              implmentation strategies.**** Note:        Requires a server machine and an aribitrary number of**              clients to bang on it. Trust the numbers on the server**              more than those being displayed by the various clients.*/#include "prerror.h"#include "prinrval.h"#include "prinit.h"#include "prio.h"#include "prlock.h"#include "prmem.h"#include "prnetdb.h"#include "prprf.h"#include "prthread.h"#include "pprio.h"#include "plerror.h"#include "plgetopt.h"#define ADDR_BUFFER 100#define PORT_NUMBER 51877#define SAMPLING_INTERVAL 10#define BUFFER_SIZE (32 * 1024)static PRInt32 domain = PR_AF_INET;static PRInt32 protocol = 6;  /* TCP */static PRFileDesc *err = NULL;static PRIntn concurrency = 1;static PRInt32 xport_buffer = -1;static PRUint32 initial_streams = 1;static PRInt32 buffer_size = BUFFER_SIZE;static PRThreadScope thread_scope = PR_LOCAL_THREAD;typedef struct Shared{    PRLock *ml;    PRUint32 sampled;    PRUint32 threads;    PRIntervalTime timein;    PRNetAddr server_address;} Shared;static Shared *shared = NULL;static PRStatus PrintAddress(const PRNetAddr* address){    char buffer[ADDR_BUFFER];    PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer));    if (PR_SUCCESS == rv)        PR_fprintf(err, "%s:%u\n", buffer, PR_ntohs(address->inet.port));    else PL_FPrintError(err, "PR_NetAddrToString");    return rv;}  /* PrintAddress */static void PR_CALLBACK Clientel(void *arg){    PRStatus rv;    PRFileDesc *xport;    PRInt32 bytes, sampled;    PRIntervalTime now, interval;    PRBool do_display = PR_FALSE;    Shared *shared = (Shared*)arg;    char *buffer = (char*)PR_Malloc(buffer_size);    PRNetAddr *server_address = &shared->server_address;    PRIntervalTime connect_timeout = PR_SecondsToInterval(5);    PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL);    PR_fprintf(err, "Client connecting to ");    (void)PrintAddress(server_address);    do    {        xport = PR_Socket(domain, PR_SOCK_STREAM, protocol);        if (NULL == xport)        {            PL_FPrintError(err, "PR_Socket");            return;        }        if (xport_buffer != -1)        {            PRSocketOptionData data;            data.option = PR_SockOpt_RecvBufferSize;            data.value.recv_buffer_size = (PRSize)xport_buffer;            rv = PR_SetSocketOption(xport, &data);            if (PR_FAILURE == rv)                PL_FPrintError(err, "PR_SetSocketOption - ignored");            data.option = PR_SockOpt_SendBufferSize;            data.value.send_buffer_size = (PRSize)xport_buffer;            rv = PR_SetSocketOption(xport, &data);            if (PR_FAILURE == rv)                PL_FPrintError(err, "PR_SetSocketOption - ignored");        }        rv = PR_Connect(xport, server_address, connect_timeout);        if (PR_FAILURE == rv)        {            PL_FPrintError(err, "PR_Connect");            if (PR_IO_TIMEOUT_ERROR != PR_GetError())                PR_Sleep(connect_timeout);            PR_Close(xport);  /* delete it and start over */        }    } while (PR_FAILURE == rv);    do    {        bytes = PR_Recv(            xport, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT);        PR_Lock(shared->ml);        now = PR_IntervalNow();        shared->sampled += bytes;        interval = now - shared->timein;        if (interval > sampling_interval)        {            sampled = shared->sampled;            shared->timein = now;            shared->sampled = 0;            do_display = PR_TRUE;        }        PR_Unlock(shared->ml);        if (do_display)        {            PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval);            PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate);            do_display = PR_FALSE;        }    } while (bytes > 0);}  /* Clientel */static void Client(const char *server_name){    PRStatus rv;    PRHostEnt host;    char buffer[PR_NETDB_BUF_SIZE];    PRIntervalTime dally = PR_SecondsToInterval(60);    PR_fprintf(err, "Translating the name %s\n", server_name);    rv = PR_GetHostByName(server_name, buffer, sizeof(buffer), &host);    if (PR_FAILURE == rv)        PL_FPrintError(err, "PR_GetHostByName");    else    {        if (PR_EnumerateHostEnt(            0, &host, PORT_NUMBER, &shared->server_address) < 0)            PL_FPrintError(err, "PR_EnumerateHostEnt");        else        {            do            {                shared->threads += 1;                (void)PR_CreateThread(                    PR_USER_THREAD, Clientel, shared,                    PR_PRIORITY_NORMAL, thread_scope,                    PR_UNJOINABLE_THREAD, 8 * 1024);                if (shared->threads == initial_streams)                {                    PR_Sleep(dally);                    initial_streams += 1;                }            } while (PR_TRUE);        }    }}static void PR_CALLBACK Servette(void *arg){    PRInt32 bytes, sampled;    PRIntervalTime now, interval;    PRBool do_display = PR_FALSE;    PRFileDesc *client = (PRFileDesc*)arg;    char *buffer = (char*)PR_Malloc(buffer_size);    PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL);    if (xport_buffer != -1)    {        PRStatus rv;        PRSocketOptionData data;        data.option = PR_SockOpt_RecvBufferSize;        data.value.recv_buffer_size = (PRSize)xport_buffer;        rv = PR_SetSocketOption(client, &data);        if (PR_FAILURE == rv)            PL_FPrintError(err, "PR_SetSocketOption - ignored");        data.option = PR_SockOpt_SendBufferSize;        data.value.send_buffer_size = (PRSize)xport_buffer;        rv = PR_SetSocketOption(client, &data);        if (PR_FAILURE == rv)            PL_FPrintError(err, "PR_SetSocketOption - ignored");    }    do    {        bytes = PR_Send(            client, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT);        PR_Lock(shared->ml);        now = PR_IntervalNow();        shared->sampled += bytes;        interval = now - shared->timein;        if (interval > sampling_interval)        {            sampled = shared->sampled;            shared->timein = now;            shared->sampled = 0;            do_display = PR_TRUE;        }        PR_Unlock(shared->ml);        if (do_display)        {            PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval);            PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate);            do_display = PR_FALSE;        }    } while (bytes > 0);}  /* Servette */static void Server(void){    PRStatus rv;    PRNetAddr server_address, client_address;    PRFileDesc *xport = PR_Socket(domain, PR_SOCK_STREAM, protocol);    if (NULL == xport)    {        PL_FPrintError(err, "PR_Socket");        return;    }    rv = PR_InitializeNetAddr(PR_IpAddrAny, PORT_NUMBER, &server_address);    if (PR_FAILURE == rv) PL_FPrintError(err, "PR_InitializeNetAddr");    else    {        rv = PR_Bind(xport, &server_address);        if (PR_FAILURE == rv) PL_FPrintError(err, "PR_Bind");        else        {            PRFileDesc *client;            rv = PR_Listen(xport, 10);            PR_fprintf(err, "Server listening on ");            (void)PrintAddress(&server_address);            do            {                client = PR_Accept(                    xport, &client_address, PR_INTERVAL_NO_TIMEOUT);                if (NULL == client) PL_FPrintError(err, "PR_Accept");                else                {                    PR_fprintf(err, "Server accepting from ");                    (void)PrintAddress(&client_address);                    shared->threads += 1;                    (void)PR_CreateThread(                        PR_USER_THREAD, Servette, client,                        PR_PRIORITY_NORMAL, thread_scope,                        PR_UNJOINABLE_THREAD, 8 * 1024);                }            } while (PR_TRUE);        }    }}  /* Server */static void Help(void){    PR_fprintf(err, "Usage: [-h] [<server>]\n");    PR_fprintf(err, "\t-s <n>   Initial # of connections        (default: 1)\n");    PR_fprintf(err, "\t-C <n>   Set 'concurrency'               (default: 1)\n");    PR_fprintf(err, "\t-b <nK>  Client buffer size              (default: 32k)\n");    PR_fprintf(err, "\t-B <nK>  Transport recv/send buffer size (default: sys)\n");    PR_fprintf(err, "\t-G       Use GLOBAL threads              (default: LOCAL)\n");    PR_fprintf(err, "\t-X       Use XTP transport               (default: TCP)\n");    PR_fprintf(err, "\t-6       Use IPv6                        (default: IPv4)\n");    PR_fprintf(err, "\t-h       This message and nothing else\n");    PR_fprintf(err, "\t<server> DNS name of server\n");    PR_fprintf(err, "\t\tIf <server> is not specified, this host will be\n");    PR_fprintf(err, "\t\tthe server and not act as a client.\n");}  /* Help */PRIntn main(PRIntn argc, char **argv){    PLOptStatus os;    const char *server_name = NULL;    PLOptState *opt = PL_CreateOptState(argc, argv, "hGX6C:b:s:B:");    err = PR_GetSpecialFD(PR_StandardError);    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))    {        if (PL_OPT_BAD == os) continue;        switch (opt->option)        {        case 0:  /* Name of server */            server_name = opt->value;            break;        case 'G':  /* Globular threads */            thread_scope = PR_GLOBAL_THREAD;            break;        case 'X':  /* Use XTP as the transport */            protocol = 36;            break;        case '6':  /* Use IPv6 */            domain = PR_AF_INET6;            break;        case 's':  /* initial_streams */            initial_streams = atoi(opt->value);            break;        case 'C':  /* concurrency */            concurrency = atoi(opt->value);            break;        case 'b':  /* buffer size */            buffer_size = 1024 * atoi(opt->value);            break;        case 'B':  /* buffer size */            xport_buffer = 1024 * atoi(opt->value);            break;        case 'h':  /* user wants some guidance */        default:            Help();  /* so give him an earful */            return 2;  /* but not a lot else */        }    }    PL_DestroyOptState(opt);    shared = PR_NEWZAP(Shared);    shared->ml = PR_NewLock();    PR_fprintf(err,        "This machine is %s\n",        (NULL == server_name) ? "the SERVER" : "a CLIENT");    PR_fprintf(err,        "Transport being used is %s\n",        (6 == protocol) ? "TCP" : "XTP");    if (PR_GLOBAL_THREAD == thread_scope)    {        if (1 != concurrency)        {            PR_fprintf(err, "  **Concurrency > 1 and GLOBAL threads!?!?\n");            PR_fprintf(err, "  **Ignoring concurrency\n");            concurrency = 1;        }    }    if (1 != concurrency)    {        PR_SetConcurrency(concurrency);        PR_fprintf(err, "Concurrency set to %u\n", concurrency);    }    PR_fprintf(err,        "All threads will be %s\n",        (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL");    PR_fprintf(err, "Client buffer size will be %u\n", buffer_size);       if (-1 != xport_buffer)    PR_fprintf(        err, "Transport send & receive buffer size will be %u\n", xport_buffer);        if (NULL == server_name) Server();    else Client(server_name);}  /* main *//* thruput.c */

⌨️ 快捷键说明

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