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

📄 sockets.c

📁 php-4.4.7学习linux时下载的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	HashTable	*new_hash;	int			num = 0;	if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;	ALLOC_HASHTABLE(new_hash);	zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0);	for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(sock_array));		 zend_hash_get_current_data(Z_ARRVAL_P(sock_array), (void **) &element) == SUCCESS;		 zend_hash_move_forward(Z_ARRVAL_P(sock_array))) {		php_sock = (php_socket*) zend_fetch_resource(element TSRMLS_CC, -1, le_socket_name, NULL, 1, le_socket);		if (!php_sock) continue; /* If element is not a resource, skip it */		if (FD_ISSET(php_sock->bsd_socket, fds)) {			/* Add fd to new array */			zend_hash_next_index_insert(new_hash, (void *)element, sizeof(zval *), (void **)&dest_element);			if (dest_element) zval_add_ref(dest_element);		}		num++;	}	/* Destroy old array, add new one */	zend_hash_destroy(Z_ARRVAL_P(sock_array));	efree(Z_ARRVAL_P(sock_array));	zend_hash_internal_pointer_reset(new_hash);	Z_ARRVAL_P(sock_array) = new_hash;	return num ? 1 : 0;}/* {{{ proto int socket_select(array &read_fds, array &write_fds, &array except_fds, int tv_sec[, int tv_usec])   Runs the select() system call on the sets mentioned with a timeout specified by tv_sec and tv_usec */PHP_FUNCTION(socket_select){	zval			*r_array, *w_array, *e_array, *sec;	struct timeval	tv;	struct timeval *tv_p = NULL;	fd_set			rfds, wfds, efds;	SOCKET			max_fd = 0;	int			retval, sets = 0;	long			usec = 0;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!z!|l", &r_array, &w_array, &e_array, &sec, &usec) == FAILURE)		return;	FD_ZERO(&rfds);	FD_ZERO(&wfds);	FD_ZERO(&efds);	if (r_array != NULL) sets += php_sock_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);	if (w_array != NULL) sets += php_sock_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);	if (e_array != NULL) sets += php_sock_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);	if (!sets) {		php_error(E_WARNING, "%s() no resource arrays were passed to select", get_active_function_name(TSRMLS_C));		RETURN_FALSE;	}	/* If seconds is not set to null, build the timeval, else we wait indefinitely */	if (sec != NULL) {		zval tmp;		if (Z_TYPE_P(sec) != IS_LONG) {			tmp = *sec;			zval_copy_ctor(&tmp);			convert_to_long(&tmp);			sec = &tmp;		}		/* Solaris + BSD do not like microsecond values which are >= 1 sec */ 		if (usec > 999999) {			tv.tv_sec = Z_LVAL_P(sec) + (usec / 1000000);			tv.tv_usec = usec % 1000000;		} else {			tv.tv_sec = Z_LVAL_P(sec);			tv.tv_usec = usec;		}				tv_p = &tv;		if (sec == &tmp) {			zval_dtor(&tmp);		}	}	retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);	if (retval == -1) {		SOCKETS_G(last_error) = errno;		php_error(E_WARNING, "%s() %s [%d]: %s", get_active_function_name(TSRMLS_C), "unable to select", errno, php_strerror(errno TSRMLS_CC));		RETURN_FALSE;	}	if (r_array != NULL) php_sock_array_from_fd_set(r_array, &rfds TSRMLS_CC);	if (w_array != NULL) php_sock_array_from_fd_set(w_array, &wfds TSRMLS_CC);	if (e_array != NULL) php_sock_array_from_fd_set(e_array, &efds TSRMLS_CC);	RETURN_LONG(retval);}/* }}} *//* {{{ proto resource socket_create_listen(int port[, int backlog])   Opens a socket on port to accept connections */PHP_FUNCTION(socket_create_listen){	php_socket	*php_sock;	long		port, backlog = 128;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &port, &backlog) == FAILURE)		return;	if (!php_open_listen_sock(&php_sock, port, backlog TSRMLS_CC)) {		RETURN_FALSE;	}	php_sock->error = 0;	ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);}/* }}} *//* {{{ proto resource socket_accept(resource socket)   Accepts a connection on the listening socket fd */PHP_FUNCTION(socket_accept){	zval				*arg1;	php_socket			*php_sock, *new_sock;	struct sockaddr_in	sa;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);		if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr *) &sa TSRMLS_CC)) {		RETURN_FALSE;	}	new_sock->error = 0;		ZEND_REGISTER_RESOURCE(return_value, new_sock, le_socket);}/* }}} *//* {{{ proto bool socket_set_nonblock(resource socket)   Sets nonblocking mode on a socket resource */PHP_FUNCTION(socket_set_nonblock){	zval		*arg1;	php_socket	*php_sock;	int			flags;   	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)		return;		ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);		flags = fcntl(php_sock->bsd_socket, F_GETFL);	/* Safely append non blocking to other flags unless the get fails.	 * Note: This does not abort on failure becuse getfl will always fail	 *       under the current win32 code. */	if (flags > -1) flags |= O_NONBLOCK;		else flags = O_NONBLOCK;		if (fcntl(php_sock->bsd_socket, F_SETFL, flags) > -1) {		RETURN_TRUE;	}	RETURN_FALSE;}/* }}} *//* {{{ proto bool socket_set_block(resource socket)   Sets blocking mode on a socket resource */PHP_FUNCTION(socket_set_block){	zval		*arg1;	php_socket	*php_sock;	int			flags;   	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)		return;		ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);		flags = fcntl(php_sock->bsd_socket, F_GETFL);	/* Safely remove blocking from flags unless the get fails.	 * Note: This does not abort on failure becuse getfl will always fail	 *       under the current win32 code. */	if (flags > -1) flags &= ~O_NONBLOCK;		else flags = 0;		if (fcntl(php_sock->bsd_socket, F_SETFL, flags) > -1) {		RETURN_TRUE;	}	RETURN_FALSE;}/* }}} *//* {{{ proto bool socket_listen(resource socket[, int backlog])   Sets the maximum number of connections allowed to be waited for on the socket specified by fd */PHP_FUNCTION(socket_listen){	zval		*arg1;	php_socket	*php_sock;	long			backlog = 0;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &backlog) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	if (listen(php_sock->bsd_socket, backlog) != 0) {		PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno);		RETURN_FALSE;	}		RETURN_TRUE;}/* }}} *//* {{{ proto void socket_close(resource socket)   Closes a file descriptor */PHP_FUNCTION(socket_close){	zval		*arg1;	php_socket	*php_sock;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	zend_list_delete(Z_RESVAL_P(arg1));}/* }}} *//* {{{ proto int socket_write(resource socket, string buf[, int length])   Writes the buffer to the socket resource, length is optional */PHP_FUNCTION(socket_write){	zval		*arg1;	php_socket	*php_sock;	int			retval, str_len;	long			length;	char		*str;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str, &str_len, &length) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	if (ZEND_NUM_ARGS() < 3) {		length = str_len;	}#ifndef PHP_WIN32	retval = write(php_sock->bsd_socket, str, MIN(length, str_len));#else	retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);#endif	if (retval < 0) {		PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);		RETURN_FALSE;	}	RETURN_LONG(retval);}/* }}} *//* {{{ proto string socket_read(resource socket, int length [, int type])   Reads a maximum of length bytes from socket */PHP_FUNCTION(socket_read){	zval		*arg1;	php_socket	*php_sock;	char		*tmpbuf;	int			retval;	long			length, type = PHP_BINARY_READ;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg1, &length, &type) == FAILURE)		return;	/* overflow check */	if((length + 1) < 2) {		RETURN_FALSE;	}	tmpbuf = emalloc(length + 1);		ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	if (type == PHP_NORMAL_READ) {		retval = php_read(php_sock->bsd_socket, tmpbuf, length, 0);	} else {		retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);	}	if (retval == -1) {		/* if the socket is in non-blocking mode and there's no data to read,		don't output any error, as this is a normal situation, and not an error */		if (errno == EAGAIN#ifdef EWOULDBLOCK		|| errno == EWOULDBLOCK#endif		) {			php_sock->error = errno;			SOCKETS_G(last_error) = errno;		} else {			PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);		}		efree(tmpbuf);		RETURN_FALSE;	}		tmpbuf = erealloc(tmpbuf, retval + 1);	tmpbuf[ retval ] = '\0' ;	RETURN_STRINGL(tmpbuf, retval, 0);}/* }}} *//* {{{ proto bool socket_getsockname(resource socket, string &addr[, int &port])   Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */PHP_FUNCTION(socket_getsockname){	zval					*arg1, *addr, *port = NULL;	php_sockaddr_storage	sa_storage;	php_socket				*php_sock;	struct sockaddr			*sa;	struct sockaddr_in		*sin;	struct sockaddr_un		*s_un;	char					*addr_string;	socklen_t				salen = sizeof(php_sockaddr_storage);	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &addr, &port) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	sa = (struct sockaddr *) &sa_storage;	if (getsockname(php_sock->bsd_socket, sa, &salen) != 0) {		PHP_SOCKET_ERROR(php_sock, "unable to retrieve socket name", errno);		RETURN_FALSE;	}		switch (sa->sa_family) {		case AF_INET:			sin = (struct sockaddr_in *) sa;			while (inet_ntoa_lock == 1);			inet_ntoa_lock = 1;			addr_string = inet_ntoa(sin->sin_addr);			inet_ntoa_lock = 0;							zval_dtor(addr);			ZVAL_STRING(addr, addr_string, 1);			if (port != NULL) {				zval_dtor(port);				ZVAL_LONG(port, htons(sin->sin_port));			}			RETURN_TRUE;		case AF_UNIX:			s_un = (struct sockaddr_un *) sa;			zval_dtor(addr);			ZVAL_STRING(addr, s_un->sun_path, 1);			RETURN_TRUE;		default:			php_error(E_WARNING, "%s() Unsupported address family %d",					  get_active_function_name(TSRMLS_C), sa->sa_family);			RETURN_FALSE;	}}/* }}} *//* {{{ proto bool socket_getpeername(resource socket, string &addr[, int &port])   Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */PHP_FUNCTION(socket_getpeername){	zval					*arg1, *arg2, *arg3 = NULL;	php_sockaddr_storage	sa_storage;	php_socket				*php_sock;	struct sockaddr			*sa;	struct sockaddr_in		*sin;	struct sockaddr_un		*s_un;	char					*addr_string;	socklen_t				salen = sizeof(php_sockaddr_storage);	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &arg1, &arg2, &arg3) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	sa = (struct sockaddr *) &sa_storage;	if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) {		PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno);		RETURN_FALSE;	}	switch (sa->sa_family) {		case AF_INET:			sin = (struct sockaddr_in *) sa;			while (inet_ntoa_lock == 1);			inet_ntoa_lock = 1;			addr_string = inet_ntoa(sin->sin_addr);			inet_ntoa_lock = 0;						zval_dtor(arg2);			ZVAL_STRING(arg2, addr_string, 1);			if (arg3 != NULL) {				zval_dtor(arg3);				ZVAL_LONG(arg3, htons(sin->sin_port));			}			RETURN_TRUE;		case AF_UNIX:			s_un = (struct sockaddr_un *) sa;			zval_dtor(arg2);			ZVAL_STRING(arg2, s_un->sun_path, 1);			RETURN_TRUE;		default:			php_error(E_WARNING, "%s() Unsupported address family %d",					  get_active_function_name(TSRMLS_C), sa->sa_family);			RETURN_FALSE;	}}/* }}} *//* {{{ proto resource socket_create(int domain, int type, int protocol)   Creates an endpoint for communication in the domain specified by domain, of type specified by type */PHP_FUNCTION(socket_create){	long			arg1, arg2, arg3;	php_socket	*php_sock = (php_socket*)emalloc(sizeof(php_socket));	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) {		efree(php_sock);		return;    }	if (arg1 != AF_UNIX && arg1 != AF_INET) {		php_error(E_WARNING, "%s() invalid socket domain [%ld] specified for argument 1, assuming AF_INET", get_active_function_name(TSRMLS_C), arg1);		arg1 = AF_INET;	}	if (arg2 > 10) {		php_error(E_WARNING, "%s() invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", get_active_function_name(TSRMLS_C), arg2);		arg2 = SOCK_STREAM;	}		php_sock->bsd_socket = socket(arg1, arg2, arg3);	php_sock->type = arg1;	if (IS_INVALID_SOCKET(php_sock)) {		SOCKETS_G(last_error) = errno;		php_error(E_WARNING, "%s() Unable to create socket [%d]: %s",				  get_active_function_name(TSRMLS_C), errno, php_strerror(errno TSRMLS_CC));		efree(php_sock);		RETURN_FALSE;	}	php_sock->error = 0;	ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);}/* }}} *//* {{{ proto bool socket_connect(resource socket, string addr [, int port])   Opens a connection to addr:port on the socket specified by socket */PHP_FUNCTION(socket_connect){	zval				*arg1;	php_socket			*php_sock;	struct sockaddr_in	sin;	struct sockaddr_un	s_un;	char				*addr;	int					retval, addr_len;	long					port;	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE)		return;	ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);	switch(php_sock->type) {		case AF_INET:			if (ZEND_NUM_ARGS() != 3) {				php_error(E_WARNING, "%s() Socket of type AF_INET requires 3 arguments",						  get_active_function_name(TSRMLS_C));				RETURN_FALSE;			}			sin.sin_family	= AF_INET;			sin.sin_port	= htons((unsigned short int)port);						if (! php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {				RETURN_FALSE;			}			retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));			break;		case AF_UNIX:			s_un.sun_family = AF_UNIX;			snprintf(s_un.sun_path, 108, "%s", addr);			retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un, SUN_LEN(&s_un));			break;		default:			php_error(E_WARNING, "%s() Unsupported socket type %d",					  get_active_function_name(TSRMLS_C), php_sock->type);			RETURN_FALSE;		}			if (retval != 0) {		PHP_SOCKET_ERROR(php_sock, "unable to connect", errno);		RETURN_FALSE;	}	RETURN_TRUE;}/* }}} *//* {{{ proto string socket_strerror(int errno)   Returns a string describing an error */PHP_FUNCTION(socket_strerror){

⌨️ 快捷键说明

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