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

📄 tclwinsock.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * Check that WinSock is initialized; do not call it if not, to     * prevent system crashes. This can happen at exit time if the exit     * handler for WinSock ran before other exit handlers that want to     * use sockets.     */    if (SocketsEnabled()) {        	/*         * Clean up the OS socket handle.  The default Windows setting	 * for a socket is SO_DONTLINGER, which does a graceful shutdown	 * in the background.         */            if ((*winSock.closesocket)(infoPtr->socket) == SOCKET_ERROR) {            TclWinConvertWSAError((*winSock.WSAGetLastError)());            errorCode = Tcl_GetErrno();        }    }    /*     * Remove the socket from socketList.     */    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);    for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL;	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {	if ((*nextPtrPtr) == infoPtr) {	    (*nextPtrPtr) = infoPtr->nextPtr;	    break;	}    }    SetEvent(tsdPtr->socketListLock);        ckfree((char *) infoPtr);    return errorCode;}/* *---------------------------------------------------------------------- * * NewSocketInfo -- * *	This function allocates and initializes a new SocketInfo *	structure. * * Results: *	Returns a newly allocated SocketInfo. * * Side effects: *	Adds the socket to the global socket list. * *---------------------------------------------------------------------- */static SocketInfo *NewSocketInfo(socket)    SOCKET socket;{    SocketInfo *infoPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    infoPtr = (SocketInfo *) ckalloc((unsigned) sizeof(SocketInfo));    infoPtr->socket = socket;    infoPtr->flags = 0;    infoPtr->watchEvents = 0;    infoPtr->readyEvents = 0;    infoPtr->selectEvents = 0;    infoPtr->acceptEventCount = 0;    infoPtr->acceptProc = NULL;    infoPtr->lastError = 0;    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);    infoPtr->nextPtr = tsdPtr->socketList;    tsdPtr->socketList = infoPtr;    SetEvent(tsdPtr->socketListLock);        return infoPtr;}/* *---------------------------------------------------------------------- * * CreateSocket -- * *	This function opens a new socket and initializes the *	SocketInfo structure. * * Results: *	Returns a new SocketInfo, or NULL with an error in interp. * * Side effects: *	Adds a new socket to the socketList. * *---------------------------------------------------------------------- */static SocketInfo *CreateSocket(interp, port, host, server, myaddr, myport, async)    Tcl_Interp *interp;		/* For error reporting; can be NULL. */    int port;			/* Port number to open. */    CONST char *host;		/* Name of host on which to open port. */    int server;			/* 1 if socket should be a server socket,				 * else 0 for a client socket. */    CONST char *myaddr;		/* Optional client-side address */    int myport;			/* Optional client-side port */    int async;			/* If nonzero, connect client socket                                 * asynchronously. */{    u_long flag = 1;			/* Indicates nonblocking mode. */    int asyncConnect = 0;		/* Will be 1 if async connect is                                         * in progress. */    struct sockaddr_in sockaddr;	/* Socket address */    struct sockaddr_in mysockaddr;	/* Socket address for client */    SOCKET sock;    SocketInfo *infoPtr;		/* The returned value. */    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    /*     * Check that WinSock is initialized; do not call it if not, to     * prevent system crashes. This can happen at exit time if the exit     * handler for WinSock ran before other exit handlers that want to     * use sockets.     */    if (!SocketsEnabled()) {        return NULL;    }    if (! CreateSocketAddress(&sockaddr, host, port)) {	goto error;    }    if ((myaddr != NULL || myport != 0) &&	    ! CreateSocketAddress(&mysockaddr, myaddr, myport)) {	goto error;    }    sock = (*winSock.socket)(AF_INET, SOCK_STREAM, 0);    if (sock == INVALID_SOCKET) {	goto error;    }    /*     * Win-NT has a misfeature that sockets are inherited in child     * processes by default.  Turn off the inherit bit.     */    SetHandleInformation( (HANDLE) sock, HANDLE_FLAG_INHERIT, 0 );	    /*     * Set kernel space buffering     */    TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE);    if (server) {	/*	 * Bind to the specified port.  Note that we must not call setsockopt	 * with SO_REUSEADDR because Microsoft allows addresses to be reused	 * even if they are still in use.         *         * Bind should not be affected by the socket having already been         * set into nonblocking mode. If there is trouble, this is one place         * to look for bugs.	 */    	if ((*winSock.bind)(sock, (struct sockaddr *) &sockaddr,		sizeof(sockaddr)) == SOCKET_ERROR) {            goto error;        }        /*         * Set the maximum number of pending connect requests to the         * max value allowed on each platform (Win32 and Win32s may be         * different, and there may be differences between TCP/IP stacks).         */        	if ((*winSock.listen)(sock, SOMAXCONN) == SOCKET_ERROR) {	    goto error;	}	/*	 * Add this socket to the global list of sockets.	 */	infoPtr = NewSocketInfo(sock);	/*	 * Set up the select mask for connection request events.	 */	infoPtr->selectEvents = FD_ACCEPT;	infoPtr->watchEvents |= FD_ACCEPT;    } else {        /*         * Try to bind to a local port, if specified.         */        	if (myaddr != NULL || myport != 0) { 	    if ((*winSock.bind)(sock, (struct sockaddr *) &mysockaddr,		    sizeof(struct sockaddr)) == SOCKET_ERROR) {		goto error;	    }	}                	/*	 * Set the socket into nonblocking mode if the connect should be	 * done in the background.	 */    	if (async) {	    if ((*winSock.ioctlsocket)(sock, FIONBIO, &flag) == SOCKET_ERROR) {		goto error;	    }	}	/*	 * Attempt to connect to the remote socket.	 */	if ((*winSock.connect)(sock, (struct sockaddr *) &sockaddr,		sizeof(sockaddr)) == SOCKET_ERROR) {            TclWinConvertWSAError((*winSock.WSAGetLastError)());	    if (Tcl_GetErrno() != EWOULDBLOCK) {		goto error;	    }	    /*	     * The connection is progressing in the background.	     */	    asyncConnect = 1;        }	/*	 * Add this socket to the global list of sockets.	 */	infoPtr = NewSocketInfo(sock);	/*	 * Set up the select mask for read/write events.  If the connect	 * attempt has not completed, include connect events.	 */	infoPtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;	if (asyncConnect) {	    infoPtr->flags |= SOCKET_ASYNC_CONNECT;	    infoPtr->selectEvents |= FD_CONNECT;	}    }    /*     * Register for interest in events in the select mask.  Note that this     * automatically places the socket into non-blocking mode.     */    (*winSock.ioctlsocket)(sock, FIONBIO, &flag);    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) infoPtr);    return infoPtr;error:    TclWinConvertWSAError((*winSock.WSAGetLastError)());    if (interp != NULL) {	Tcl_AppendResult(interp, "couldn't open socket: ",		Tcl_PosixError(interp), (char *) NULL);    }    if (sock != INVALID_SOCKET) {	(*winSock.closesocket)(sock);    }    return NULL;}/* *---------------------------------------------------------------------- * * CreateSocketAddress -- * *	This function initializes a sockaddr structure for a host and port. * * Results: *	1 if the host was valid, 0 if the host could not be converted to *	an IP address. * * Side effects: *	Fills in the *sockaddrPtr structure. * *---------------------------------------------------------------------- */static intCreateSocketAddress(sockaddrPtr, host, port)    struct sockaddr_in *sockaddrPtr;	/* Socket address */    CONST char *host;			/* Host.  NULL implies INADDR_ANY */    int port;				/* Port number */{    struct hostent *hostent;		/* Host database entry */    struct in_addr addr;		/* For 64/32 bit madness */    /*     * Check that WinSock is initialized; do not call it if not, to     * prevent system crashes. This can happen at exit time if the exit     * handler for WinSock ran before other exit handlers that want to     * use sockets.     */    if (!SocketsEnabled()) {        Tcl_SetErrno(EFAULT);        return 0;    }    (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));    sockaddrPtr->sin_family = AF_INET;    sockaddrPtr->sin_port = (*winSock.htons)((short) (port & 0xFFFF));    if (host == NULL) {	addr.s_addr = INADDR_ANY;    } else {        addr.s_addr = (*winSock.inet_addr)(host);        if (addr.s_addr == INADDR_NONE) {            hostent = (*winSock.gethostbyname)(host);            if (hostent != NULL) {                memcpy((char *) &addr,                        (char *) hostent->h_addr_list[0],                        (size_t) hostent->h_length);            } else {#ifdef	EHOSTUNREACH                Tcl_SetErrno(EHOSTUNREACH);#else#ifdef ENXIO                Tcl_SetErrno(ENXIO);#endif#endif		return 0;	/* Error. */	    }	}    }    /*     * NOTE: On 64 bit machines the assignment below is rumored to not     * do the right thing. Please report errors related to this if you     * observe incorrect behavior on 64 bit machines such as DEC Alphas.     * Should we modify this code to do an explicit memcpy?     */    sockaddrPtr->sin_addr.s_addr = addr.s_addr;    return 1;	/* Success. */}/* *---------------------------------------------------------------------- * * WaitForSocketEvent -- * *	Waits until one of the specified events occurs on a socket. * * Results: *	Returns 1 on success or 0 on failure, with an error code in *	errorCodePtr. * * Side effects: *	Processes socket events off the system queue. * *---------------------------------------------------------------------- */static intWaitForSocketEvent(infoPtr, events, errorCodePtr)    SocketInfo *infoPtr;	/* Information about this socket. */    int events;			/* Events to look for. */    int *errorCodePtr;		/* Where to store errors? */{    int result = 1;    int oldMode;    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    /*     * Be sure to disable event servicing so we are truly modal.     */    oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);        /*     * Reset WSAAsyncSelect so we have a fresh set of events pending.     */    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) UNSELECT, (LPARAM) infoPtr);    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) infoPtr);    while (1) {	if (infoPtr->lastError) {	    *errorCodePtr = infoPtr->lastError;	    result = 0;	    break;	} else if (infoPtr->readyEvents & events) {	    break;	} else if (infoPtr->flags & SOCKET_ASYNC) {	    *errorCodePtr = EWOULDBLOCK;	    result = 0;	    break;	}	/*	 * Wait until something happens.	 */	WaitForSingleObject(tsdPtr->readyEvent, INFINITE);    }        (void) Tcl_SetServiceMode(oldMode);    return result;}/* *---------------------------------------------------------------------- * * Tcl_OpenTcpClient -- * *	Opens a TCP client socket and creates a channel around it. * * Results: *	The channel or NULL if failed.  An error message is returned *	in the interpreter on failure. * * Side effects: *	Opens a client socket and creates a new channel. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_OpenTcpClient(interp, port, host, myaddr, myport, async)    Tcl_Interp *interp;			/* For error reporting; can be NULL. */    int port;				/* Port number to open. */    CONST char *host;			/* Host on which to open port. */    CONST char *myaddr;			/* Client-side address */    int myport;				/* Client-side port */    int async;				/* If nonzero, should connect                                         * client socket asynchronously. */{    SocketInfo *infoPtr;    char channelName[16 + TCL_INTEGER_SPACE];    if (TclpHasSockets(interp) != TCL_OK) {	return NULL;

⌨️ 快捷键说明

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