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

📄 tclwinsock.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclWinSock.c -- * *	This file contains Windows-specific socket related code. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinSock.c,v 1.36 2003/01/16 19:02:00 mdejong Exp $ */#include "tclWinInt.h"/* * Make sure to remove the redirection defines set in tclWinPort.h * that is in use in other sections of the core, except for us. */#undef getservbyname#undef getsockopt#undef ntohs#undef setsockopt/* * The following variable is used to tell whether this module has been * initialized. */static int initialized = 0;static int  hostnameInitialized = 0;static char hostname[255];	/* This buffer should be big enough for                                 * hostname plus domain name. */TCL_DECLARE_MUTEX(socketMutex)/* * Mingw and Cygwin may not have LPFN_* typedefs. */#ifdef HAVE_NO_LPFN_DECLS    typedef SOCKET (PASCAL FAR *LPFN_ACCEPT)(SOCKET s,            struct sockaddr FAR * addr, int FAR * addrlen);    typedef int (PASCAL FAR *LPFN_BIND)(SOCKET s,            const struct sockaddr FAR *addr, int namelen);    typedef int (PASCAL FAR *LPFN_CLOSESOCKET)(SOCKET s);    typedef int (PASCAL FAR *LPFN_CONNECT)(SOCKET s,            const struct sockaddr FAR *name, int namelen);    typedef struct hostent FAR * (PASCAL FAR *LPFN_GETHOSTBYADDR)            (const char FAR *addr, int addrlen, int addrtype);    typedef struct hostent FAR * (PASCAL FAR *LPFN_GETHOSTBYNAME)            (const char FAR * name);    typedef int (PASCAL FAR *LPFN_GETHOSTNAME)(char FAR * name,            int namelen);    typedef int (PASCAL FAR *LPFN_GETPEERNAME)(SOCKET sock,            struct sockaddr FAR *name, int FAR *namelen);    typedef struct servent FAR * (PASCAL FAR *LPFN_GETSERVBYNAME)            (const char FAR * name, const char FAR * proto);    typedef int (PASCAL FAR *LPFN_GETSOCKNAME)(SOCKET sock,            struct sockaddr FAR *name, int FAR *namelen);    typedef int (PASCAL FAR *LPFN_GETSOCKOPT)(SOCKET s, int level,            int optname, char FAR * optval, int FAR *optlen);    typedef u_short (PASCAL FAR *LPFN_HTONS)(u_short hostshort);    typedef unsigned long (PASCAL FAR *LPFN_INET_ADDR)            (const char FAR * cp);    typedef char FAR * (PASCAL FAR *LPFN_INET_NTOA)            (struct in_addr in);    typedef int (PASCAL FAR *LPFN_IOCTLSOCKET)(SOCKET s,            long cmd, u_long FAR *argp);    typedef int (PASCAL FAR *LPFN_LISTEN)(SOCKET s, int backlog);    typedef u_short (PASCAL FAR *LPFN_NTOHS)(u_short netshort);    typedef int (PASCAL FAR *LPFN_RECV)(SOCKET s, char FAR * buf,            int len, int flags);    typedef int (PASCAL FAR *LPFN_SELECT)(int nfds,            fd_set FAR * readfds, fd_set FAR * writefds,            fd_set FAR * exceptfds,            const struct timeval FAR * timeout);    typedef int (PASCAL FAR *LPFN_SEND)(SOCKET s,            const char FAR * buf, int len, int flags);    typedef int (PASCAL FAR *LPFN_SETSOCKOPT)(SOCKET s,            int level, int optname, const char FAR * optval,            int optlen);    typedef SOCKET (PASCAL FAR *LPFN_SOCKET)(int af,            int type, int protocol);    typedef int (PASCAL FAR *LPFN_WSAASYNCSELECT)(SOCKET s,            HWND hWnd, u_int wMsg, long lEvent);    typedef int (PASCAL FAR *LPFN_WSACLEANUP)(void);    typedef int (PASCAL FAR *LPFN_WSAGETLASTERROR)(void);    typedef int (PASCAL FAR *LPFN_WSASTARTUP)(WORD wVersionRequired,            LPWSADATA lpWSAData);#endif/* * The following structure contains pointers to all of the WinSock API * entry points used by Tcl.  It is initialized by InitSockets.  Since * we dynamically load the Winsock DLL on demand, we must use this * function table to refer to functions in the winsock API. */static struct {    HMODULE		    hModule;	/* Handle to WinSock library. */    /* Winsock 1.1 functions */    LPFN_ACCEPT		    accept;    LPFN_BIND		    bind;    LPFN_CLOSESOCKET	    closesocket;    LPFN_CONNECT	    connect;    LPFN_GETHOSTBYADDR	    gethostbyaddr;    LPFN_GETHOSTBYNAME	    gethostbyname;    LPFN_GETHOSTNAME	    gethostname;    LPFN_GETPEERNAME	    getpeername;    LPFN_GETSERVBYNAME	    getservbyname;    LPFN_GETSOCKNAME	    getsockname;    LPFN_GETSOCKOPT	    getsockopt;    LPFN_HTONS		    htons;    LPFN_INET_ADDR	    inet_addr;    LPFN_INET_NTOA	    inet_ntoa;    LPFN_IOCTLSOCKET	    ioctlsocket;    LPFN_LISTEN		    listen;    LPFN_NTOHS		    ntohs;    LPFN_RECV		    recv;    LPFN_SELECT		    select;    LPFN_SEND		    send;    LPFN_SETSOCKOPT	    setsockopt;    LPFN_SOCKET		    socket;    LPFN_WSAASYNCSELECT	    WSAAsyncSelect;    LPFN_WSACLEANUP	    WSACleanup;    LPFN_WSAGETLASTERROR    WSAGetLastError;    LPFN_WSASTARTUP	    WSAStartup;} winSock;/* * The following defines declare the messages used on socket windows. */#define SOCKET_MESSAGE	    WM_USER+1#define SOCKET_SELECT	    WM_USER+2#define SOCKET_TERMINATE    WM_USER+3#define SELECT		    TRUE#define UNSELECT	    FALSE/* * The following structure is used to store the data associated with * each socket. */typedef struct SocketInfo {    Tcl_Channel channel;	   /* Channel associated with this				    * socket. */    SOCKET socket;		   /* Windows SOCKET handle. */    int flags;			   /* Bit field comprised of the flags				    * described below.  */    int watchEvents;		   /* OR'ed combination of FD_READ,				    * FD_WRITE, FD_CLOSE, FD_ACCEPT and				    * FD_CONNECT that indicate which				    * events are interesting. */    int readyEvents;		   /* OR'ed combination of FD_READ,				    * FD_WRITE, FD_CLOSE, FD_ACCEPT and				    * FD_CONNECT that indicate which				    * events have occurred. */    int selectEvents;		   /* OR'ed combination of FD_READ,				    * FD_WRITE, FD_CLOSE, FD_ACCEPT and				    * FD_CONNECT that indicate which				    * events are currently being				    * selected. */    int acceptEventCount;          /* Count of the current number of				    * FD_ACCEPTs that have arrived and				    * not yet processed. */    Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */    ClientData acceptProcData;	   /* The data for the accept proc. */    int lastError;		   /* Error code from last message. */    struct SocketInfo *nextPtr;	   /* The next socket on the per-thread				    * socket list. */} SocketInfo;/* * The following structure is what is added to the Tcl event queue when * a socket event occurs. */typedef struct SocketEvent {    Tcl_Event header;		/* Information that is standard for				 * all events. */    SOCKET socket;		/* Socket descriptor that is ready.  Used				 * to find the SocketInfo structure for				 * the file (can't point directly to the				 * SocketInfo structure because it could				 * go away while the event is queued). */} SocketEvent;/* * This defines the minimum buffersize maintained by the kernel. */#define TCP_BUFFER_SIZE 4096/* * The following macros may be used to set the flags field of * a SocketInfo structure. */#define SOCKET_ASYNC		(1<<0)	/* The socket is in blocking					 * mode. */#define SOCKET_EOF		(1<<1)	/* A zero read happened on					 * the socket. */#define SOCKET_ASYNC_CONNECT	(1<<2)	/* This socket uses async					 * connect. */#define SOCKET_PENDING		(1<<3)	/* A message has been sent					 * for this socket */typedef struct ThreadSpecificData {    HWND hwnd;		    /* Handle to window for socket messages. */    HANDLE socketThread;    /* Thread handling the window */    Tcl_ThreadId threadId;  /* Parent thread. */    HANDLE readyEvent;      /* Event indicating that a socket event is			     * ready.  Also used to indicate that the			     * socketThread has been initialized and has			     * started. */    HANDLE socketListLock;  /* Win32 Event to lock the socketList */    SocketInfo *socketList; /* Every open socket in this thread has an			     * entry on this list. */} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;static WNDCLASS windowClass;/* * Static functions defined in this file. */static SocketInfo *	    CreateSocket _ANSI_ARGS_((Tcl_Interp *interp,				    int port, CONST char *host,				    int server, CONST char *myaddr,				    int myport, int async));static int		    CreateSocketAddress _ANSI_ARGS_(				    (LPSOCKADDR_IN sockaddrPtr,				    CONST char *host, int port));static void		    InitSockets _ANSI_ARGS_((void));static SocketInfo *	    NewSocketInfo _ANSI_ARGS_((SOCKET socket));static Tcl_EventCheckProc   SocketCheckProc;static Tcl_EventProc	    SocketEventProc;static void		    SocketExitHandler _ANSI_ARGS_((				    ClientData clientData));static LRESULT CALLBACK	    SocketProc _ANSI_ARGS_((HWND hwnd,				    UINT message, WPARAM wParam,				    LPARAM lParam));static Tcl_EventSetupProc   SocketSetupProc;static Tcl_ExitProc	    SocketThreadExitHandler;static int		    SocketsEnabled _ANSI_ARGS_((void));static void		    TcpAccept _ANSI_ARGS_((SocketInfo *infoPtr));static Tcl_DriverBlockModeProc	TcpBlockProc;static Tcl_DriverCloseProc	TcpCloseProc;static Tcl_DriverSetOptionProc	TcpSetOptionProc;static Tcl_DriverGetOptionProc	TcpGetOptionProc;static Tcl_DriverInputProc	TcpInputProc;static Tcl_DriverOutputProc	TcpOutputProc;static Tcl_DriverWatchProc	TcpWatchProc;static Tcl_DriverGetHandleProc	TcpGetHandleProc;static int		    WaitForSocketEvent _ANSI_ARGS_((				SocketInfo *infoPtr, int events,				int *errorCodePtr));static DWORD WINAPI	    SocketThread _ANSI_ARGS_((LPVOID arg));/* * This structure describes the channel type structure for TCP socket * based IO. */static Tcl_ChannelType tcpChannelType = {    "tcp",		    /* Type name. */    TCL_CHANNEL_VERSION_2,  /* v2 channel */    TcpCloseProc,	    /* Close proc. */    TcpInputProc,	    /* Input proc. */    TcpOutputProc,	    /* Output proc. */    NULL,		    /* Seek proc. */    TcpSetOptionProc,	    /* Set option proc. */    TcpGetOptionProc,	    /* Get option proc. */    TcpWatchProc,	    /* Set up notifier to watch this channel. */    TcpGetHandleProc,	    /* Get an OS handle from channel. */    NULL,		    /* close2proc. */    TcpBlockProc,	    /* Set socket into (non-)blocking mode. */    NULL,		    /* flush proc. */    NULL,		    /* handler proc. */};/* *---------------------------------------------------------------------- * * InitSockets -- * *	Initialize the socket module.  Attempts to load the wsock32.dll *	library and set up the winSock function table.  If successful, *	registers the event window for the socket notifier code. * *	Assumes Mutex is held. * * Results: *	None. * * Side effects: *	Dynamically loads wsock32.dll, and registers a new window *	class and creates a window for use in asynchronous socket *	notification. * *---------------------------------------------------------------------- */static voidInitSockets(){    DWORD id;    WSADATA wsaData;    DWORD err;    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (!initialized) {	initialized = 1;	Tcl_CreateExitHandler(SocketExitHandler, (ClientData) NULL);	winSock.hModule = LoadLibraryA("wsock32.dll");	if (winSock.hModule == NULL) {	    return;	}    	/*	 * Initialize the function table.	 */	winSock.accept = (LPFN_ACCEPT)		GetProcAddress(winSock.hModule, "accept");	winSock.bind = (LPFN_BIND)		GetProcAddress(winSock.hModule, "bind");	winSock.closesocket = (LPFN_CLOSESOCKET)		GetProcAddress(winSock.hModule, "closesocket");	winSock.connect = (LPFN_CONNECT)		GetProcAddress(winSock.hModule, "connect");	winSock.gethostbyaddr = (LPFN_GETHOSTBYADDR)		GetProcAddress(winSock.hModule, "gethostbyaddr");	winSock.gethostbyname = (LPFN_GETHOSTBYNAME)		GetProcAddress(winSock.hModule, "gethostbyname");	winSock.gethostname = (LPFN_GETHOSTNAME)		GetProcAddress(winSock.hModule, "gethostname");	winSock.getpeername = (LPFN_GETPEERNAME)		GetProcAddress(winSock.hModule, "getpeername");	winSock.getservbyname = (LPFN_GETSERVBYNAME)		GetProcAddress(winSock.hModule, "getservbyname");	winSock.getsockname = (LPFN_GETSOCKNAME)		GetProcAddress(winSock.hModule, "getsockname");	winSock.getsockopt = (LPFN_GETSOCKOPT)		GetProcAddress(winSock.hModule, "getsockopt");	winSock.htons = (LPFN_HTONS)		GetProcAddress(winSock.hModule, "htons");	winSock.inet_addr = (LPFN_INET_ADDR)		GetProcAddress(winSock.hModule, "inet_addr");	winSock.inet_ntoa = (LPFN_INET_NTOA)		GetProcAddress(winSock.hModule, "inet_ntoa");	winSock.ioctlsocket = (LPFN_IOCTLSOCKET)		GetProcAddress(winSock.hModule, "ioctlsocket");	winSock.listen = (LPFN_LISTEN)		GetProcAddress(winSock.hModule, "listen");	winSock.ntohs = (LPFN_NTOHS)		GetProcAddress(winSock.hModule, "ntohs");	winSock.recv = (LPFN_RECV)		GetProcAddress(winSock.hModule, "recv");	winSock.select = (LPFN_SELECT)		GetProcAddress(winSock.hModule, "select");	winSock.send = (LPFN_SEND)		GetProcAddress(winSock.hModule, "send");	winSock.setsockopt = (LPFN_SETSOCKOPT)		GetProcAddress(winSock.hModule, "setsockopt");	winSock.socket = (LPFN_SOCKET)		GetProcAddress(winSock.hModule, "socket");	winSock.WSAAsyncSelect = (LPFN_WSAASYNCSELECT)		GetProcAddress(winSock.hModule, "WSAAsyncSelect");	winSock.WSACleanup = (LPFN_WSACLEANUP)		GetProcAddress(winSock.hModule, "WSACleanup");	winSock.WSAGetLastError = (LPFN_WSAGETLASTERROR)		GetProcAddress(winSock.hModule, "WSAGetLastError");	winSock.WSAStartup = (LPFN_WSASTARTUP)		GetProcAddress(winSock.hModule, "WSAStartup");    	/*	 * Now check that all fields are properly initialized. If not,	 * return zero to indicate that we failed to initialize	 * properly.	 */    	if ((winSock.accept == NULL) ||		(winSock.bind == NULL) ||		(winSock.closesocket == NULL) ||		(winSock.connect == NULL) ||		(winSock.gethostbyname == NULL) ||		(winSock.gethostbyaddr == NULL) ||		(winSock.gethostname == NULL) ||		(winSock.getpeername == NULL) ||		(winSock.getservbyname == NULL) ||		(winSock.getsockname == NULL) ||		(winSock.getsockopt == NULL) ||		(winSock.htons == NULL) ||		(winSock.inet_addr == NULL) ||		(winSock.inet_ntoa == NULL) ||		(winSock.ioctlsocket == NULL) ||		(winSock.listen == NULL) ||		(winSock.ntohs == NULL) ||		(winSock.recv == NULL) ||		(winSock.select == NULL) ||		(winSock.send == NULL) ||		(winSock.setsockopt == NULL) ||		(winSock.socket == NULL) ||		(winSock.WSAAsyncSelect == NULL) ||		(winSock.WSACleanup == NULL) ||		(winSock.WSAGetLastError == NULL) ||		(winSock.WSAStartup == NULL))	{	    goto unloadLibrary;	}		/*	 * Create the async notification window with a new class.  We	 * must create a new class to avoid a Windows 95 bug that causes	 * us to get the wrong message number for socket events if the	 * message window is a subclass of a static control.	 */    	windowClass.style = 0;	windowClass.cbClsExtra = 0;	windowClass.cbWndExtra = 0;	windowClass.hInstance = TclWinGetTclInstance();	windowClass.hbrBackground = NULL;	windowClass.lpszMenuName = NULL;	windowClass.lpszClassName = "TclSocket";	windowClass.lpfnWndProc = SocketProc;	windowClass.hIcon = NULL;	windowClass.hCursor = NULL;	if (!RegisterClassA(&windowClass)) {	    TclWinConvertError(GetLastError());	    goto unloadLibrary;	}	/*	 * Initialize the winsock library and check the interface	 * version actually loaded. We only ask for the 1.1 interface	 * and do require that it not be less than 1.1.	 */#define WSA_VERSION_MAJOR   1#define WSA_VERSION_MINOR   1#define WSA_VERSION_REQD    MAKEWORD(WSA_VERSION_MAJOR, WSA_VERSION_MINOR)	if ((err = winSock.WSAStartup(WSA_VERSION_REQD, &wsaData)) != 0) {	    TclWinConvertWSAError(err);	    goto unloadLibrary;	}	/*	 * Note the byte positions are swapped for the comparison, so

⌨️ 快捷键说明

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