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

📄 tclwinsock.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
    infoPtr = NewSocketInfo((SOCKET) sock);    /*     * Start watching for read/write events on the socket.     */    infoPtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE;    (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,	    SOCKET_MESSAGE, infoPtr->selectEvents);    sprintf(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. */    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[20];    if (TclHasSockets(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;    sprintf(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[20];    /*     * 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.     */    infoPtr->readyEvents &= ~(FD_ACCEPT);    if (newSocket == INVALID_SOCKET) {        return;    }    /*     * 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);    (void) (*winSock.WSAAsyncSelect)(newInfoPtr->socket, winSock.hwnd, 	    SOCKET_MESSAGE, newInfoPtr->selectEvents);    sprintf(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;        *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 (winSock.hInstance == NULL) {        *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) {	(void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,		0, 0);	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;	}    }        (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,	    SOCKET_MESSAGE, infoPtr->selectEvents);    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. */    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;    *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 (winSock.hInstance == NULL) {        *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) {	(void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,		0, 0);	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;	}    }    (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,	    SOCKET_MESSAGE, infoPtr->selectEvents);    return bytesWritten;}/* *---------------------------------------------------------------------- * * 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 */    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. */{

⌨️ 快捷键说明

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