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

📄 socket.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- 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. *//*************************************************************************** Name: socket.c**** Description: Test socket functionality.**** Modification History:*/#include "primpl.h"#include "plgetopt.h"#include <stdio.h>#include <string.h>#include <errno.h>#ifdef XP_UNIX#include <sys/mman.h>#endif#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)#include <pthread.h>#endif#ifdef WIN32#include <process.h>#endifstatic int _debug_on = 0;static int test_cancelio = 0;#ifdef XP_MAC#include "prlog.h"#include "prsem.h"int fprintf(FILE *stream, const char *fmt, ...){    PR_LogPrint(fmt);    return 0;}#define printf PR_LogPrintextern void SetupMacPrintfLog(char *logFile);#else#include "obsolete/prsem.h"#endif#ifdef XP_PC#define mode_t int#endif#define DPRINTF(arg) if (_debug_on) printf arg#ifdef XP_PCchar *TEST_DIR = "prdir";char *SMALL_FILE_NAME = "prsmallf";char *LARGE_FILE_NAME = "prlargef";#elsechar *TEST_DIR = "/tmp/prsocket_test_dir";char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";#endif#define SMALL_FILE_SIZE				(3 * 1024)        /* 3 KB        */#define SMALL_FILE_OFFSET_1			(512)#define SMALL_FILE_LEN_1			(1 * 1024)        /* 1 KB        */#define SMALL_FILE_OFFSET_2			(75)#define SMALL_FILE_LEN_2			(758)#define SMALL_FILE_OFFSET_3			(1024)#define SMALL_FILE_LEN_3			(SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3)#define SMALL_FILE_HEADER_SIZE    	(64)            /* 64 bytes    */#define SMALL_FILE_TRAILER_SIZE   	(128)           /* 128 bytes    */#define LARGE_FILE_SIZE				(3 * 1024 * 1024)    /* 3 MB        */#define LARGE_FILE_OFFSET_1			(0)#define LARGE_FILE_LEN_1			(2 * 1024 * 1024)    /* 2 MB        */#define LARGE_FILE_OFFSET_2			(64)#define LARGE_FILE_LEN_2			(1 * 1024 * 1024 + 75)#define LARGE_FILE_OFFSET_3			(2 * 1024 * 1024 - 128)#define LARGE_FILE_LEN_3			(LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3)#define LARGE_FILE_OFFSET_4			PR_GetPageSize()#define LARGE_FILE_LEN_4			769#define LARGE_FILE_HEADER_SIZE    	(512)#define LARGE_FILE_TRAILER_SIZE   	(64)#define    BUF_DATA_SIZE    (2 * 1024)#define TCP_MESG_SIZE    1024/* * set UDP datagram size small enough that datagrams sent to a port on the * local host will not be lost */#define UDP_DGRAM_SIZE            128#define NUM_TCP_CLIENTS            5	/* for a listen queue depth of 5 */#define NUM_UDP_CLIENTS            10#ifndef XP_MAC#define NUM_TRANSMITFILE_CLIENTS    4#else/* Mac can't handle more than 2* (3Mb) allocations for large file size buffers */#define NUM_TRANSMITFILE_CLIENTS    2#endif#define NUM_TCP_CONNECTIONS_PER_CLIENT    5#define NUM_TCP_MESGS_PER_CONNECTION    10#define NUM_UDP_DATAGRAMS_PER_CLIENT    5#define TCP_SERVER_PORT            10000#define UDP_SERVER_PORT            TCP_SERVER_PORT#define SERVER_MAX_BIND_COUNT        100static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;static PRInt32 num_udp_clients = NUM_UDP_CLIENTS;static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS;static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT;static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE;static PRInt32 thread_count;PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET;/* an I/O layer that uses the emulated senfile method */static PRDescIdentity emuSendFileIdentity;static PRIOMethods emuSendFileMethods;int failed_already=0;typedef struct buffer {    char    data[BUF_DATA_SIZE];} buffer;PRNetAddr tcp_server_addr, udp_server_addr;typedef struct Serve_Client_Param {    PRFileDesc *sockfd;    /* socket to read from/write to    */    PRInt32    datalen;    /* bytes of data transfered in each read/write */} Serve_Client_Param;typedef struct Server_Param {    PRSemaphore *addr_sem;    /* sem to post on, after setting up the address */    PRMonitor *exit_mon;    /* monitor to signal on exit            */    PRInt32 *exit_counter;    /* counter to decrement, before exit        */    PRInt32    datalen;    /* bytes of data transfered in each read/write    */} Server_Param;typedef struct Client_Param {    PRNetAddr server_addr;    PRMonitor *exit_mon;    /* monitor to signal on exit */    PRInt32 *exit_counter;    /* counter to decrement, before exit */    PRInt32    datalen;    PRInt32    udp_connect;    /* if set clients connect udp sockets */} Client_Param;/* the sendfile method in emuSendFileMethods */static PRInt32 PR_CALLBACKemu_SendFile(PRFileDesc *sd, PRSendFileData *sfd,    PRTransmitFileFlags flags, PRIntervalTime timeout){    return PR_EmulateSendFile(sd, sfd, flags, timeout);}/* the transmitfile method in emuSendFileMethods */static PRInt32 PR_CALLBACKemu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers,    PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout){    PRSendFileData sfd;    sfd.fd = fd;    sfd.file_offset = 0;    sfd.file_nbytes = 0;    sfd.header = headers;    sfd.hlen = hlen;    sfd.trailer = NULL;    sfd.tlen = 0;    return emu_SendFile(sd, &sfd, flags, timeout);}/* * readn *    read data from sockfd into buf */static PRInt32readn(PRFileDesc *sockfd, char *buf, int len){    int rem;    int bytes;    int offset = 0;	int err;	PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;	if (test_cancelio)		timeout = PR_SecondsToInterval(2);    for (rem=len; rem; offset += bytes, rem -= bytes) {        DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",            PR_GetCurrentThread(), rem));retry:        bytes = PR_Recv(sockfd, buf + offset, rem, 0,            	timeout);        DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",            PR_GetCurrentThread(), bytes));        if (bytes < 0) {#ifdef WINNT			printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()),									PR_GetOSError());			if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) {				if (PR_NT_CancelIo(sockfd) != PR_SUCCESS)					printf("PR_NT_CancelIO: error = %d\n",PR_GetError());				timeout = PR_INTERVAL_NO_TIMEOUT;				goto retry;			}#endif			return -1;		}	    }    return len;}/* * writen *    write data from buf to sockfd */static PRInt32writen(PRFileDesc *sockfd, char *buf, int len){    int rem;    int bytes;    int offset = 0;    for (rem=len; rem; offset += bytes, rem -= bytes) {        DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",            PR_GetCurrentThread(), rem));        bytes = PR_Send(sockfd, buf + offset, rem, 0,            PR_INTERVAL_NO_TIMEOUT);        DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",            PR_GetCurrentThread(), bytes));        if (bytes <= 0)            return -1;    }    return len;}/* * Serve_Client *    Thread, started by the server, for serving a client connection. *    Reads data from socket and writes it back, unmodified, and *    closes the socket */static void PR_CALLBACKServe_Client(void *arg){    Serve_Client_Param *scp = (Serve_Client_Param *) arg;    PRFileDesc *sockfd;    buffer *in_buf;    PRInt32 bytes, j;    sockfd = scp->sockfd;    bytes = scp->datalen;    in_buf = PR_NEW(buffer);    if (in_buf == NULL) {        fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");        failed_already=1;        goto exit;    }    for (j = 0; j < num_tcp_mesgs_per_connection; j++) {        /*         * Read data from client and send it back to the client unmodified         */        if (readn(sockfd, in_buf->data, bytes) < bytes) {            fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n");            failed_already=1;            goto exit;        }        /*         * shutdown reads, after the last read         */        if (j == num_tcp_mesgs_per_connection - 1)            if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) {                fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");            }        DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(),            (*((int *) in_buf->data))));        if (writen(sockfd, in_buf->data, bytes) < bytes) {            fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n");            failed_already=1;            goto exit;        }    }    /*     * shutdown reads and writes     */    if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {        fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");        failed_already=1;    }exit:    PR_Close(sockfd);    if (in_buf) {        PR_DELETE(in_buf);    }}PRThread* create_new_thread(PRThreadType type,							void (*start)(void *arg),							void *arg,							PRThreadPriority priority,							PRThreadScope scope,							PRThreadState state,							PRUint32 stackSize, PRInt32 index){PRInt32 native_thread = 0;	PR_ASSERT(state == PR_UNJOINABLE_THREAD);#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)	switch(index %  4) {		case 0:			scope = (PR_LOCAL_THREAD);			break;		case 1:			scope = (PR_GLOBAL_THREAD);			break;		case 2:			scope = (PR_GLOBAL_BOUND_THREAD);			break;		case 3:			native_thread = 1;			break;		default:			PR_ASSERT(!"Invalid scope");			break;	}	if (native_thread) {#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)		pthread_t tid;		if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))			return((PRThread *) tid);		else			return (NULL);#else		HANDLE thandle;		unsigned tid;				thandle = (HANDLE) _beginthreadex(						NULL,						stackSize,						(unsigned (__stdcall *)(void *))start,						arg,						0,						&tid);				return((PRThread *) thandle);#endif	} else {		return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));	}#else	return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));#endif}/* * TCP Server *    Server Thread *    Bind an address to a socket and listen for incoming connections *    Start a Serve_Client thread for each incoming connection. */static void PR_CALLBACKTCP_Server(void *arg){    PRThread *t;    Server_Param *sp = (Server_Param *) arg;    Serve_Client_Param *scp;    PRFileDesc *sockfd, *newsockfd;    PRNetAddr netaddr;    PRInt32 i;    /*     * Create a tcp socket     */	if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) {        fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");        goto exit;    }    memset(&netaddr, 0 , sizeof(netaddr));		if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT,									&netaddr) == PR_FAILURE) {        fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");        goto exit;	}    /*     * try a few times to bind server's address, if addresses are in     * use     */    i = 0;	    while (PR_Bind(sockfd, &netaddr) < 0) {        if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {            netaddr.inet.port += 2;            if (i++ < SERVER_MAX_BIND_COUNT)

⌨️ 快捷键说明

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