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

📄 socket.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: socket.c,v 1.5.2.13.2.13 2004/09/01 04:32:18 marka Exp $ *//* This code has been rewritten to take advantage of Windows Sockets * I/O Completion Ports and Events. I/O Completion Ports is ONLY * available on Windows NT, Windows 2000 and Windows XP series of * the Windows Operating Systems. In CANNOT run on Windows 95, Windows 98 * or the follow-ons to those Systems. * * This code is by nature multithreaded and takes advantage of various * features to pass on information through the completion port for * when I/O is completed.  All sends and receives are completed through * the completion port. Due to an implementation bug in Windows 2000, * Service Pack 2 must installed on the system for this code to run correctly. * For details on this problem see Knowledge base article Q263823. * The code checks for this. The number of Completion Port Worker threads * used is the total number of CPU's + 1. This increases the likelihood that * a Worker Thread is available for processing a completed request. * * All accepts and connects are accomplished through the WSAEventSelect() * function and the event_wait loop. Events are added to and deleted from * each event_wait thread via a common event_update stack owned by the socket * manager. If the event_wait thread runs out of array space in the events * array it will look for another event_wait thread to add the event. If it * fails to find another one it will create a new thread to handle the * outstanding event. * * A future enhancement is to use AcceptEx to take avantage of Overlapped * I/O which allows for enhanced performance of TCP connections. * This will also reduce the number of events that are waited on by the * event_wait threads to just the connect sockets and reduce the number * additional threads required. * * XXXPDM 5 August, 2002 */#define MAKE_EXTERNAL 1#include <config.h>#include <sys/types.h>#ifndef _WINSOCKAPI_#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */#endif#include <errno.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <io.h>#include <fcntl.h>#include <process.h>#include <isc/buffer.h>#include <isc/bufferlist.h>#include <isc/condition.h>#include <isc/list.h>#include <isc/log.h>#include <isc/mem.h>#include <isc/msgs.h>#include <isc/mutex.h>#include <isc/net.h>#include <isc/os.h>#include <isc/platform.h>#include <isc/print.h>#include <isc/region.h>#include <isc/socket.h>#include <isc/strerror.h>#include <isc/syslog.h>#include <isc/task.h>#include <isc/thread.h>#include <isc/util.h>#include <isc/win32os.h>#include "errno2result.h"/* * Define this macro to control the behavior of connection * resets on UDP sockets.  See Microsoft KnowledgeBase Article Q263823 * for details. * NOTE: This requires that Windows 2000 systems install Service Pack 2 * or later. */#ifndef SIO_UDP_CONNRESET #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif/* * Some systems define the socket length argument as an int, some as size_t, * some as socklen_t.  This is here so it can be easily changed if needed. */#ifndef ISC_SOCKADDR_LEN_T#define ISC_SOCKADDR_LEN_T unsigned int#endif/* * Define what the possible "soft" errors can be.  These are non-fatal returns * of various network related functions, like recv() and so on. * * For some reason, BSDI (and perhaps others) will sometimes return <0 * from recv() but will have errno==0.  This is broken, but we have to * work around it here. */#define SOFT_ERROR(e)	((e) == WSAEINTR || \			 (e) == WSA_IO_PENDING || \			 (e) == WSAEWOULDBLOCK || \			 (e) == EWOULDBLOCK || \			 (e) == EINTR || \			 (e) == EAGAIN || \			 (e) == 0)#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)/* * DLVL(90)  --  Function entry/exit and other tracing. * DLVL(70)  --  Socket "correctness" -- including returning of events, etc. * DLVL(60)  --  Socket data send/receive * DLVL(50)  --  Event tracing, including receiving/sending completion events. * DLVL(20)  --  Socket creation/destruction. */#define TRACE_LEVEL		90#define CORRECTNESS_LEVEL	70#define IOEVENT_LEVEL		60#define EVENT_LEVEL		50#define CREATION_LEVEL		20#define TRACE		DLVL(TRACE_LEVEL)#define CORRECTNESS	DLVL(CORRECTNESS_LEVEL)#define IOEVENT		DLVL(IOEVENT_LEVEL)#define EVENT		DLVL(EVENT_LEVEL)#define CREATION	DLVL(CREATION_LEVEL)typedef isc_event_t intev_t;#define SOCKET_MAGIC		ISC_MAGIC('I', 'O', 'i', 'o')#define VALID_SOCKET(t)		ISC_MAGIC_VALID(t, SOCKET_MAGIC)/* * IPv6 control information.  If the socket is an IPv6 socket we want * to collect the destination address and interface so the client can * set them on outgoing packets. */#ifdef ISC_PLATFORM_HAVEIPV6#ifndef USE_CMSG#define USE_CMSG	1#endif#endif/* * NetBSD and FreeBSD can timestamp packets.  XXXMLG Should we have * a setsockopt() like interface to request timestamps, and if the OS * doesn't do it for us, call gettimeofday() on every UDP receive? *//* * We really  don't want to try and use these control messages. Win32 * doesn't have this mechanism */#undef USE_CMSG/* * Message header for recvmsg and sendmsg calls. * Used value-result for recvmsg, value only for sendmsg. */struct msghdr {        void	*msg_name;              /* optional address */        u_int   msg_namelen;            /* size of address */        WSABUF  *msg_iov;		/* scatter/gather array */        u_int   msg_iovlen;             /* # elements in msg_iov */        void	*msg_control;           /* ancillary data, see below */        u_int   msg_controllen;         /* ancillary data buffer len */        int     msg_flags;              /* flags on received message */} msghdr;	/* * The number of times a send operation is repeated if the result is EINTR. */#define NRETRIES 10struct isc_socket {	/* Not locked. */	unsigned int		magic;	isc_socketmgr_t	       *manager;	isc_mutex_t		lock;	isc_sockettype_t	type;	OVERLAPPED		overlapped;	/* Pointers to scatter/gather buffers */	WSABUF			iov[ISC_SOCKET_MAXSCATTERGATHER];	size_t			totalBytes;	WSAEVENT		hEvent;		/* Event Handle */	long			wait_type;	/* Events to wait on */	WSAEVENT		hAlert;		/* Alert Event Handle */	DWORD			evthread_id;	/* Event Thread Id for socket */	/* Locked by socket lock. */	ISC_LINK(isc_socket_t)	link;	unsigned int		references;	SOCKET			fd;	int			pf;	ISC_LIST(isc_socketevent_t)		send_list;	ISC_LIST(isc_socketevent_t)		recv_list;	ISC_LIST(isc_socket_newconnev_t)	accept_list;	isc_socket_connev_t		       *connect_ev;	/*	 * Internal events.  Posted when a descriptor is readable or	 * writable.  These are statically allocated and never freed.	 * They will be set to non-purgable before use.	 */	intev_t			readable_ev;	intev_t			writable_ev;	isc_sockaddr_t		address;  /* remote address */	unsigned int		pending_close : 1,				pending_accept : 1,				iocp : 1,	/* I/O Completion Port */				listener : 1,	/* listener socket */				connected : 1,				connecting : 1, /* connect pending */				bound : 1,	/* bound to local addr */				pending_free: 1;	unsigned int		pending_recv;	unsigned int		pending_send;};/* * I/O Completion ports Info structures */static HANDLE hHeapHandle = NULL;static int iocp_total = 0;typedef struct IoCompletionInfo {	OVERLAPPED			overlapped;	isc_socketevent_t		*dev;	int				request_type;	struct msghdr			messagehdr;} IoCompletionInfo;/* * Define a maximum number of I/O Completion Port worker threads * to handle the load on the Completion Port. The actual number * used is the number of CPU's + 1. */#define MAX_IOCPTHREADS 20/* * event_change structure to handle adds and deletes from the list of * events in the Wait */typedef struct event_change event_change_t;struct event_change {	isc_socket_t			*sock;	WSAEVENT			hEvent;	DWORD				evthread_id;	SOCKET				fd;	unsigned int			action;	ISC_LINK(event_change_t)	link;};/* * Note: We are using an array here since *WaitForMultiple* wants an array * WARNING: This value may not be greater than 64 since the  * WSAWaitForMultipleEvents function is limited to 64 events. */#define MAX_EVENTS 64/* * List of events being waited on and their associated sockets */typedef struct sock_event_list {	int max_event;	int total_events;	isc_socket_t			*aSockList[MAX_EVENTS];	WSAEVENT			aEventList[MAX_EVENTS];} sock_event_list;/* * Thread Event structure for managing the threads handling events */typedef struct events_thread events_thread_t;struct events_thread {	isc_thread_t			thread_handle;	/* Thread's handle */	DWORD				thread_id;	/* Thread's id */	sock_event_list			sockev_list;	isc_socketmgr_t			*manager;	ISC_LINK(events_thread_t)	link;};#define SOCKET_MANAGER_MAGIC	ISC_MAGIC('I', 'O', 'm', 'g')#define VALID_MANAGER(m)	ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)struct isc_socketmgr {	/* Not locked. */	unsigned int			magic;	isc_mem_t		       *mctx;	isc_mutex_t			lock;	/* Locked by manager lock. */	ISC_LIST(event_change_t)	event_updates;	ISC_LIST(isc_socket_t)		socklist;	int				event_written;	WSAEVENT			prime_alert;	isc_boolean_t			bShutdown;	ISC_LIST(events_thread_t)	ev_threads;	isc_condition_t			shutdown_ok;	HANDLE				hIoCompletionPort;	int				maxIOCPThreads;	HANDLE				hIOCPThreads[MAX_IOCPTHREADS];	DWORD				dwIOCPThreadIds[MAX_IOCPTHREADS];};#define CLOSED		0	/* this one must be zero */#define MANAGED		1#define CLOSE_PENDING	2/* * send() and recv() iovec counts */#define MAXSCATTERGATHER_SEND	(ISC_SOCKET_MAXSCATTERGATHER)#define MAXSCATTERGATHER_RECV	(ISC_SOCKET_MAXSCATTERGATHER)static isc_threadresult_t WINAPI event_wait(void *uap);static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);static void free_socket(isc_socket_t **);enum {	SOCKET_RECV,	SOCKET_SEND,};enum {	EVENT_ADD,	EVENT_DELETE};#if defined(ISC_SOCKET_DEBUG)/* * This is used to dump the contents of the sock structure * You should make sure that the sock is locked before * dumping it. Since the code uses simple printf() statements * it should only be used interactively. */voidsock_dump(isc_socket_t *sock) {	isc_socketevent_t *ldev;	isc_socket_newconnev_t *ndev;	isc_sockaddr_t addr;	char socktext[256];	isc_socket_getpeername(sock, &addr);	isc_sockaddr_format(&addr, socktext, sizeof(socktext));	printf("Remote Socket: %s\n", socktext);	isc_socket_getsockname(sock, &addr);	isc_sockaddr_format(&addr, socktext, sizeof(socktext));	printf("This Socket: %s\n", socktext);	printf("\n\t\tSock Dump\n");	printf("\t\tfd: %u\n", sock->fd);	printf("\t\treferences: %d\n", sock->references);	printf("\t\tpending_accept: %d\n", sock->pending_accept);	printf("\t\tpending_close: %d\n", sock->pending_close);	printf("\t\tconnecting: %d\n", sock->connecting);	printf("\t\tconnected: %d\n", sock->connected);	printf("\t\tbound: %d\n", sock->bound);	printf("\t\tiocp: %d\n", sock->iocp);	printf("\t\tsocket type: %d\n", sock->type);	printf("\n\t\tSock Recv List\n");	ldev = ISC_LIST_HEAD(sock->recv_list);	while (ldev != NULL) {		printf("\t\tdev: %p\n", ldev);		ldev = ISC_LIST_NEXT(ldev, ev_link);	}	printf("\n\t\tSock Send List\n");	ldev = ISC_LIST_HEAD(sock->send_list);	while (ldev != NULL) {		printf("\t\tdev: %p\n", ldev);		ldev = ISC_LIST_NEXT(ldev, ev_link);	}	printf("\n\t\tSock Accept List\n");	ndev = ISC_LIST_HEAD(sock->accept_list);	while (ndev != NULL) {		printf("\t\tdev: %p\n", ldev);		ndev = ISC_LIST_NEXT(ndev, ev_link);	}}#endif/*  This function will add an entry to the I/O completion port *  that will signal the I/O thread to exit (gracefully) */static voidsignal_iocompletionport_exit(isc_socketmgr_t *manager) {	int i;	int errval;	char strbuf[ISC_STRERRORSIZE];	REQUIRE(VALID_MANAGER(manager));	for (i = 0; i < manager->maxIOCPThreads; i++) {		if (!PostQueuedCompletionStatus(manager->hIoCompletionPort,						0, 0, 0)) {			errval = GetLastError();			isc__strerror(errval, strbuf, sizeof(strbuf));			FATAL_ERROR(__FILE__, __LINE__,				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,				ISC_MSG_FAILED,				"Can't request service thread to exit: %s"),				strbuf);		}	}}/* * Create the worker threads for the I/O Completion Port */voidiocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {	int errval;	char strbuf[ISC_STRERRORSIZE];	int i;	INSIST(total_threads > 0);	REQUIRE(VALID_MANAGER(manager));	/*	 * We need at least one	 */	for (i = 0; i < total_threads; i++) {		manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,						manager, 0,						&manager->dwIOCPThreadIds[i]);		if(manager->hIOCPThreads[i] == NULL) {			errval = GetLastError();			isc__strerror(errval, strbuf, sizeof(strbuf));			FATAL_ERROR(__FILE__, __LINE__,				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,				ISC_MSG_FAILED,				"Can't create IOCP thread: %s"),				strbuf);		}	}}/* *  Create/initialise the I/O completion port */voidiocompletionport_init(isc_socketmgr_t *manager) {	int errval;	char strbuf[ISC_STRERRORSIZE];	REQUIRE(VALID_MANAGER(manager));	/*	 * Create a private heap to handle the socket overlapped structure	 * The miniumum number of structures is 10, there is no maximum	 */	hHeapHandle = HeapCreate(0, 10*sizeof(IoCompletionInfo), 0);	manager->maxIOCPThreads = min(isc_os_ncpus() + 1,					MAX_IOCPTHREADS);	/* Now Create the Completion Port */	manager->hIoCompletionPort = CreateIoCompletionPort(				     INVALID_HANDLE_VALUE, NULL,				     0, manager->maxIOCPThreads);	if (manager->hIoCompletionPort == NULL) {		errval = GetLastError();		isc__strerror(errval, strbuf, sizeof(strbuf));		FATAL_ERROR(__FILE__, __LINE__,				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,				ISC_MSG_FAILED,				"CreateIoCompletionPort() failed "				"during initialization: %s"),				strbuf);		exit(1);	}		/*

⌨️ 快捷键说明

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