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

📄 tclwinsock.c

📁 最新版的BCC, bcc-src-1.0.29c.rar,基于sparc平台处理器leon2,leon3,v7,v8等系列的linux环境下交叉编译工具
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    /*     * Create a new client socket and wrap it in a channel.     */    infoPtr = CreateSocket(interp, port, host, 0, myaddr, myport, async);    if (infoPtr == NULL) {	return NULL;    }    wsprintfA(channelName, "sock%d", infoPtr->socket);    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-translation",	    "auto crlf") == TCL_ERROR) {        Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);        return (Tcl_Channel) NULL;    }    if (Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "")	    == TCL_ERROR) {        Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);        return (Tcl_Channel) NULL;    }    return infoPtr->channel;}/* *---------------------------------------------------------------------- * * Tcl_MakeTcpClientChannel -- * *	Creates a Tcl_Channel from an existing client TCP socket. * * Results: *	The Tcl_Channel wrapped around the preexisting TCP socket. * * Side effects: *	None. * * NOTE: Code contributed by Mark Diekhans (markd@grizzly.com) * *---------------------------------------------------------------------- */Tcl_ChannelTcl_MakeTcpClientChannel(sock)    ClientData sock;		/* The socket to wrap up into a channel. */{    SocketInfo *infoPtr;    char channelName[16 + TCL_INTEGER_SPACE];    ThreadSpecificData *tsdPtr;    if (TclpHasSockets(NULL) != TCL_OK) {	return NULL;    }    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    /*     * Set kernel space buffering and non-blocking.     */    TclSockMinimumBuffers((SOCKET) sock, TCP_BUFFER_SIZE);    infoPtr = NewSocketInfo((SOCKET) sock);    /*     * Start watching for read/write events on the socket.     */    infoPtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) infoPtr);    wsprintfA(channelName, "sock%d", infoPtr->socket);    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,	    (ClientData) infoPtr, (TCL_READABLE | TCL_WRITABLE));    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto crlf");    return infoPtr->channel;}/* *---------------------------------------------------------------------- * * Tcl_OpenTcpServer -- * *	Opens a TCP server 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 server socket and creates a new channel. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_OpenTcpServer(interp, port, host, acceptProc, acceptProcData)    Tcl_Interp *interp;			/* For error reporting - may be                                         * NULL. */    int port;				/* Port number to open. */    CONST char *host;			/* Name of local host. */    Tcl_TcpAcceptProc *acceptProc;	/* Callback for accepting connections                                         * from new clients. */    ClientData acceptProcData;		/* Data for the callback. */{    SocketInfo *infoPtr;    char channelName[16 + TCL_INTEGER_SPACE];    if (TclpHasSockets(interp) != TCL_OK) {	return NULL;    }    /*     * Create a new client socket and wrap it in a channel.     */    infoPtr = CreateSocket(interp, port, host, 1, NULL, 0, 0);    if (infoPtr == NULL) {	return NULL;    }    infoPtr->acceptProc = acceptProc;    infoPtr->acceptProcData = acceptProcData;    wsprintfA(channelName, "sock%d", infoPtr->socket);    infoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,	    (ClientData) infoPtr, 0);    if (Tcl_SetChannelOption(interp, infoPtr->channel, "-eofchar", "")	    == TCL_ERROR) {        Tcl_Close((Tcl_Interp *) NULL, infoPtr->channel);        return (Tcl_Channel) NULL;    }    return infoPtr->channel;}/* *---------------------------------------------------------------------- * * TcpAccept -- *	Accept a TCP socket connection.  This is called by *	SocketEventProc and it in turns calls the registered accept *	procedure. * * Results: *	None. * * Side effects: *	Invokes the accept proc which may invoke arbitrary Tcl code. * *---------------------------------------------------------------------- */static voidTcpAccept(infoPtr)    SocketInfo *infoPtr;	/* Socket to accept. */{    SOCKET newSocket;    SocketInfo *newInfoPtr;    struct sockaddr_in addr;    int len;    char channelName[16 + TCL_INTEGER_SPACE];    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    /*     * Accept the incoming connection request.     */    len = sizeof(struct sockaddr_in);    newSocket = (*winSock.accept)(infoPtr->socket,	    (struct sockaddr *)&addr,	    &len);        /*     * Clear the ready mask so we can detect the next connection request.     * Note that connection requests are level triggered, so if there is     * a request already pending, a new event will be generated.     */        if (newSocket == INVALID_SOCKET) {	infoPtr->acceptEventCount = 0;	infoPtr->readyEvents &= ~(FD_ACCEPT);	return;    }     /*     * It is possible that more than one FD_ACCEPT has been sent, so an extra     * count must be kept.  Decrement the count, and reset the readyEvent bit     * if the count is no longer > 0.     */        infoPtr->acceptEventCount--;    if (infoPtr->acceptEventCount <= 0) {	infoPtr->readyEvents &= ~(FD_ACCEPT);    }    /*     * Win-NT has a misfeature that sockets are inherited in child     * processes by default.  Turn off the inherit bit.     */        SetHandleInformation( (HANDLE) newSocket, HANDLE_FLAG_INHERIT, 0 );        /*     * Add this socket to the global list of sockets.     */        newInfoPtr = NewSocketInfo(newSocket);        /*     * Select on read/write events and create the channel.     */        newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE);    SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) newInfoPtr);        wsprintfA(channelName, "sock%d", newInfoPtr->socket);    newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,	    (ClientData) newInfoPtr, (TCL_READABLE | TCL_WRITABLE));    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation",	    "auto crlf") == TCL_ERROR) {	Tcl_Close((Tcl_Interp *) NULL, newInfoPtr->channel);	return;    }    if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-eofchar", "")	    == TCL_ERROR) {	Tcl_Close((Tcl_Interp *) NULL, newInfoPtr->channel);	return;    }        /*     * Invoke the accept callback procedure.     */        if (infoPtr->acceptProc != NULL) {	(infoPtr->acceptProc) (infoPtr->acceptProcData,		newInfoPtr->channel,		(*winSock.inet_ntoa)(addr.sin_addr),		(*winSock.ntohs)(addr.sin_port));    }}/* *---------------------------------------------------------------------- * * TcpInputProc -- * *	This procedure is called by the generic IO level to read data from *	a socket based channel. * * Results: *	The number of bytes read or -1 on error. * * Side effects: *	Consumes input from the socket. * *---------------------------------------------------------------------- */static intTcpInputProc(instanceData, buf, toRead, errorCodePtr)    ClientData instanceData;		/* The socket state. */    char *buf;				/* Where to store data. */    int toRead;				/* Maximum number of bytes to read. */    int *errorCodePtr;			/* Where to store error codes. */{    SocketInfo *infoPtr = (SocketInfo *) instanceData;    int bytesRead;    int error;    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);        *errorCodePtr = 0;    /*     * 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()) {        *errorCodePtr = EFAULT;        return -1;    }    /*     * First check to see if EOF was already detected, to prevent     * calling the socket stack after the first time EOF is detected.     */    if (infoPtr->flags & SOCKET_EOF) {	return 0;    }    /*     * Check to see if the socket is connected before trying to read.     */    if ((infoPtr->flags & SOCKET_ASYNC_CONNECT)	    && ! WaitForSocketEvent(infoPtr,  FD_CONNECT, errorCodePtr)) {	return -1;    }        /*     * No EOF, and it is connected, so try to read more from the socket.     * Note that we clear the FD_READ bit because read events are level     * triggered so a new event will be generated if there is still data     * available to be read.  We have to simulate blocking behavior here     * since we are always using non-blocking sockets.     */    while (1) {	SendMessage(tsdPtr->hwnd, SOCKET_SELECT,		(WPARAM) UNSELECT, (LPARAM) infoPtr);	bytesRead = (*winSock.recv)(infoPtr->socket, buf, toRead, 0);	infoPtr->readyEvents &= ~(FD_READ);  	/*	 * Check for end-of-file condition or successful read.	 */  	if (bytesRead == 0) {	    infoPtr->flags |= SOCKET_EOF;	}	if (bytesRead != SOCKET_ERROR) {	    break;	}  	/*	 * If an error occurs after the FD_CLOSE has arrived,	 * then ignore the error and report an EOF.	 */  	if (infoPtr->readyEvents & FD_CLOSE) {	    infoPtr->flags |= SOCKET_EOF;	    bytesRead = 0;	    break;	}  	/*	 * Check for error condition or underflow in non-blocking case.	 */  	error = (*winSock.WSAGetLastError)();	if ((infoPtr->flags & SOCKET_ASYNC) || (error != WSAEWOULDBLOCK)) {	    TclWinConvertWSAError(error);	    *errorCodePtr = Tcl_GetErrno();	    bytesRead = -1;	    break;	}	/*	 * In the blocking case, wait until the file becomes readable	 * or closed and try again.	 */	if (!WaitForSocketEvent(infoPtr, FD_READ|FD_CLOSE, errorCodePtr)) {	    bytesRead = -1;	    break;  	}    }        SendMessage(tsdPtr->hwnd, SOCKET_SELECT,	    (WPARAM) SELECT, (LPARAM) infoPtr);        return bytesRead;}/* *---------------------------------------------------------------------- * * TcpOutputProc -- * *	This procedure is called by the generic IO level to write data *	to a socket based channel. * * Results: *	The number of bytes written or -1 on failure. * * Side effects: *	Produces output on the socket. * *---------------------------------------------------------------------- */static intTcpOutputProc(instanceData, buf, toWrite, errorCodePtr)    ClientData instanceData;		/* The socket state. */    CONST char *buf;			/* Where to get data. */    int toWrite;			/* Maximum number of bytes to write. */    int *errorCodePtr;			/* Where to store error codes. */{    SocketInfo *infoPtr = (SocketInfo *) instanceData;    int bytesWritten;    int error;    ThreadSpecificData *tsdPtr = 	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    *errorCodePtr = 0;    /*     * 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()) {        *errorCodePtr = EFAULT;        return -1;    }    /*     * Check to see if the socket is connected before trying to write.     */        if ((infoPtr->flags & SOCKET_ASYNC_CONNECT)	    && ! WaitForSocketEvent(infoPtr,  FD_CONNECT, errorCodePtr)) {	return -1;    }    while (1) {	SendMessage(tsdPtr->hwnd, SOCKET_SELECT,		(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.

⌨️ 快捷键说明

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