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

📄 tclwinsock.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
		(WPARAM) UNSELECT, (LPARAM) infoPtr);	bytesWritten = winSock.send(infoPtr->socket, buf, toWrite, 0);	if (bytesWritten != SOCKET_ERROR) {	    /*	     * Since Windows won't generate a new write event until we hit	     * an overflow condition, we need to force the event loop to	     * poll until the condition changes.	     */	    if (infoPtr->watchEvents & FD_WRITE) {		Tcl_Time blockTime = { 0, 0 };		Tcl_SetMaxBlockTime(&blockTime);	    }			    break;	}		/*	 * Check for error condition or overflow.  In the event of overflow, we	 * need to clear the FD_WRITE flag so we can detect the next writable	 * event.  Note that Windows only sends a new writable event after a	 * send fails with WSAEWOULDBLOCK.	 */	error = winSock.WSAGetLastError();	if (error == WSAEWOULDBLOCK) {	    infoPtr->readyEvents &= ~(FD_WRITE);	    if (infoPtr->flags & SOCKET_ASYNC) {		*errorCodePtr = EWOULDBLOCK;		bytesWritten = -1;		break;	    } 	} else {	    TclWinConvertWSAError(error);	    *errorCodePtr = Tcl_GetErrno();	    bytesWritten = -1;	    break;	}	/*	 * In the blocking case, wait until the file becomes writable	 * or closed and try again.	 */	if (!WaitForSocketEvent(infoPtr, FD_WRITE|FD_CLOSE, errorCodePtr)) {	    bytesWritten = -1;	    break;	}    }    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) infoPtr);        return bytesWritten;}/* *---------------------------------------------------------------------- * * TcpSetOptionProc -- * *	Sets Tcp channel specific options. * * Results: *	None, unless an error happens. * * Side effects: *	Changes attributes of the socket at the system level. * *---------------------------------------------------------------------- */static intTcpSetOptionProc (    ClientData instanceData,	/* Socket state. */    Tcl_Interp *interp,		/* For error reporting - can be NULL. */    CONST char *optionName,	/* Name of the option to set. */    CONST char *value)		/* New value for option. */{    SocketInfo *infoPtr;    SOCKET sock;/*    BOOL val = FALSE;    int boolVar, rtn;*/    /*     * 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()) {	if (interp) {	    Tcl_AppendResult(interp, "winsock is not initialized", NULL);	}        return TCL_ERROR;    }    infoPtr = (SocketInfo *) instanceData;    sock = infoPtr->socket;/*    if (!stricmp(optionName, "-keepalive")) {	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {	    return TCL_ERROR;	}	if (boolVar) val = TRUE;	rtn = winSock.setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,		(const char *) &val, sizeof(BOOL));	if (rtn != 0) {	    TclWinConvertWSAError(winSock.WSAGetLastError());	    if (interp) {		Tcl_AppendResult(interp, "couldn't set socket option: ",			Tcl_PosixError(interp), NULL);	    }	    return TCL_ERROR;	}	return TCL_OK;    } else if (!stricmp(optionName, "-nagle")) {	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {	    return TCL_ERROR;	}	if (!boolVar) val = TRUE;	rtn = winSock.setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,		(const char *) &val, sizeof(BOOL));	if (rtn != 0) {	    TclWinConvertWSAError(winSock.WSAGetLastError());	    if (interp) {		Tcl_AppendResult(interp, "couldn't set socket option: ",			Tcl_PosixError(interp), NULL);	    }	    return TCL_ERROR;	}	return TCL_OK;    }    return Tcl_BadChannelOption(interp, optionName, "keepalive nagle");*/    return Tcl_BadChannelOption(interp, optionName, "");}/* *---------------------------------------------------------------------- * * TcpGetOptionProc -- * *	Computes an option value for a TCP socket based channel, or a *	list of all options and their values. * *	Note: This code is based on code contributed by John Haxby. * * Results: *	A standard Tcl result. The value of the specified option or a *	list of all options and	their values is returned in the *	supplied DString. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intTcpGetOptionProc(instanceData, interp, optionName, dsPtr)    ClientData instanceData;		/* Socket state. */    Tcl_Interp *interp;                 /* For error reporting - can be NULL */    CONST char *optionName;		/* Name of the option to                                         * retrieve the value for, or                                         * NULL to get all options and                                         * their values. */    Tcl_DString *dsPtr;			/* Where to store the computed                                         * value; initialized by caller. */{    SocketInfo *infoPtr;    SOCKADDR_IN sockname;    SOCKADDR_IN peername;    struct hostent *hostEntPtr;    SOCKET sock;    int size = sizeof(SOCKADDR_IN);    size_t len = 0;    char buf[TCL_INTEGER_SPACE];    /*     * 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()) {	if (interp) {	    Tcl_AppendResult(interp, "winsock is not initialized", NULL);	}        return TCL_ERROR;    }        infoPtr = (SocketInfo *) instanceData;    sock = (int) infoPtr->socket;    if (optionName != (char *) NULL) {        len = strlen(optionName);    }    if ((len > 1) && (optionName[1] == 'e') &&	    (strncmp(optionName, "-error", len) == 0)) {	int optlen;	DWORD err;	int ret;    	optlen = sizeof(int);	ret = TclWinGetSockOpt(sock, SOL_SOCKET, SO_ERROR,		(char *)&err, &optlen);	if (ret == SOCKET_ERROR) {	    err = winSock.WSAGetLastError();	}	if (err) {	    TclWinConvertWSAError(err);	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), -1);	}	return TCL_OK;    }    if ((len == 0) ||            ((len > 1) && (optionName[1] == 'p') &&                    (strncmp(optionName, "-peername", len) == 0))) {        if (winSock.getpeername(sock, (LPSOCKADDR) &peername, &size)                == 0) {            if (len == 0) {                Tcl_DStringAppendElement(dsPtr, "-peername");                Tcl_DStringStartSublist(dsPtr);            }            Tcl_DStringAppendElement(dsPtr,                    winSock.inet_ntoa(peername.sin_addr));	    if (peername.sin_addr.s_addr == 0) {	        hostEntPtr = (struct hostent *) NULL;	    } else {	        hostEntPtr = winSock.gethostbyaddr(                    (char *) &(peername.sin_addr), sizeof(peername.sin_addr),		    AF_INET);	    }            if (hostEntPtr != (struct hostent *) NULL) {                Tcl_DStringAppendElement(dsPtr, hostEntPtr->h_name);            } else {                Tcl_DStringAppendElement(dsPtr,                        winSock.inet_ntoa(peername.sin_addr));            }	    TclFormatInt(buf, winSock.ntohs(peername.sin_port));            Tcl_DStringAppendElement(dsPtr, buf);            if (len == 0) {                Tcl_DStringEndSublist(dsPtr);            } else {                return TCL_OK;            }        } else {            /*             * getpeername failed - but if we were asked for all the options             * (len==0), don't flag an error at that point because it could             * be an fconfigure request on a server socket. (which have             * no peer). {copied from unix/tclUnixChan.c}             */            if (len) {		TclWinConvertWSAError((DWORD) winSock.WSAGetLastError());                if (interp) {                    Tcl_AppendResult(interp, "can't get peername: ",                                     Tcl_PosixError(interp),                                     (char *) NULL);                }                return TCL_ERROR;            }        }    }    if ((len == 0) ||            ((len > 1) && (optionName[1] == 's') &&                    (strncmp(optionName, "-sockname", len) == 0))) {        if (winSock.getsockname(sock, (LPSOCKADDR) &sockname, &size)                == 0) {            if (len == 0) {                Tcl_DStringAppendElement(dsPtr, "-sockname");                Tcl_DStringStartSublist(dsPtr);            }            Tcl_DStringAppendElement(dsPtr,                    winSock.inet_ntoa(sockname.sin_addr));	    if (sockname.sin_addr.s_addr == 0) {	        hostEntPtr = (struct hostent *) NULL;	    } else {	        hostEntPtr = winSock.gethostbyaddr(                    (char *) &(sockname.sin_addr), sizeof(peername.sin_addr),		    AF_INET);	    }            if (hostEntPtr != (struct hostent *) NULL) {                Tcl_DStringAppendElement(dsPtr, hostEntPtr->h_name);            } else {                Tcl_DStringAppendElement(dsPtr,                        winSock.inet_ntoa(sockname.sin_addr));            }            TclFormatInt(buf, winSock.ntohs(sockname.sin_port));            Tcl_DStringAppendElement(dsPtr, buf);            if (len == 0) {                Tcl_DStringEndSublist(dsPtr);            } else {                return TCL_OK;            }        } else {	    if (interp) {		TclWinConvertWSAError((DWORD) winSock.WSAGetLastError());		Tcl_AppendResult(interp, "can't get sockname: ",				 Tcl_PosixError(interp),				 (char *) NULL);	    }	    return TCL_ERROR;	}    }/*    if (len == 0 || !strncmp(optionName, "-keepalive", len)) {	int optlen;	BOOL opt = FALSE;            if (len == 0) {            Tcl_DStringAppendElement(dsPtr, "-keepalive");        }	optlen = sizeof(BOOL);	winSock.getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt,		&optlen);	if (opt) {	    Tcl_DStringAppendElement(dsPtr, "1");	} else {	    Tcl_DStringAppendElement(dsPtr, "0");	}	if (len > 0) return TCL_OK;    }    if (len == 0 || !strncmp(optionName, "-nagle", len)) {	int optlen;	BOOL opt = FALSE;            if (len == 0) {            Tcl_DStringAppendElement(dsPtr, "-nagle");        }	optlen = sizeof(BOOL);	winSock.getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt,		&optlen);	if (opt) {	    Tcl_DStringAppendElement(dsPtr, "0");	} else {	    Tcl_DStringAppendElement(dsPtr, "1");	}	if (len > 0) return TCL_OK;    }*/    if (len > 0) {        /*return Tcl_BadChannelOption(interp, optionName, "peername sockname keepalive nagle");*/        return Tcl_BadChannelOption(interp, optionName, "peername sockname");    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * TcpWatchProc -- * *	Informs the channel driver of the events that the generic *	channel code wishes to receive on this socket. * * Results: *	None. * * Side effects: *	May cause the notifier to poll if any of the specified  *	conditions are already true. * *---------------------------------------------------------------------- */static voidTcpWatchProc(instanceData, mask)    ClientData instanceData;		/* The socket state. */    int mask;				/* Events of interest; an OR-ed                                         * combination of TCL_READABLE,                                         * TCL_WRITABLE and TCL_EXCEPTION. */{    SocketInfo *infoPtr = (SocketInfo *) instanceData;        /*     * Update the watch events mask. Only if the socket is not a     * server socket. Fix for SF Tcl Bug #557878.     */    if (!infoPtr->acceptProc) {            infoPtr->watchEvents = 0;	if (mask & TCL_READABLE) {	    infoPtr->watchEvents |= (FD_READ|FD_CLOSE|FD_ACCEPT);	}	if (mask & TCL_WRITABLE) {	    infoPtr->watchEvents |= (FD_WRITE|FD_CONNECT);	}      	/*	 * If there are any conditions already set, then tell the notifier to poll	 * rather than block.	 */	if (infoPtr->readyEvents & infoPtr->watchEvents) {	    Tcl_Time blockTime = { 0, 0 };	    Tcl_SetMaxBlockTime(&blockTime);	}    }}/* *---------------------------------------------------------------------- * * TcpGetProc -- * *	Called from Tcl_GetChannelHandle to retrieve an OS handle from inside *	a TCP socket based channel. * * Results: *	Returns TCL_OK with the socket in handlePtr. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intTcpGetHandleProc(instanceData, direction, handlePtr)    ClientData instanceData;	/* The socket state. */    int direction;		/* Not used. */    ClientData *handlePtr;	/* Where to store the handle.  */{    SocketInfo *statePtr = (SocketInfo *) instanceData;    *handlePtr = (ClientData) statePtr->socket;    return TCL_OK;}/* *---------------------------------------------------------------------- * * SocketThread -- * *	Helper thread used to manage the socket event handling window. * * Results: *	1 if unable to create socket event window, 0 otherwise. * * Side effects: *	None. * *---------------------------------------------------------------------- */static DWORD WINAPISocketThread(LPVOID arg){    M

⌨️ 快捷键说明

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