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

📄 tclwinsock.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * 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. */    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. */    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. */    /*     * 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) {        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;    }    /*     * 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);    (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,	    SOCKET_MESSAGE, infoPtr->selectEvents);    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 */    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 (winSock.hInstance == NULL) {        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? */{    MSG msg;    int result = 1;    int oldMode;    /*     * 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.     */    (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd, 0, 0);    (void) (*winSock.WSAAsyncSelect)(infoPtr->socket, winSock.hwnd,	    SOCKET_MESSAGE, infoPtr->selectEvents);    while (1) {	/*	 * Process all outstanding messages on the socket window.	 */	while (PeekMessage(&msg, winSock.hwnd, 0, 0, PM_REMOVE)) {	    DispatchMessage(&msg);	}		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.	 */	WaitMessage();    }        (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. */    char *host;				/* Host on which to open port. */    char *myaddr;			/* Client-side address */    int myport;				/* Client-side port */    int async;				/* If nonzero, should connect                                         * client socket asynchronously. */{    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, 0, myaddr, myport, async);    if (infoPtr == NULL) {	return NULL;    }    sprintf(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[20];    if (TclHasSockets(NULL) != TCL_OK) {	return NULL;    }    /*     * Set kernel space buffering and non-blocking.     */    TclSockMinimumBuffers((SOCKET) sock, TCP_BUFFER_SIZE);

⌨️ 快捷键说明

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