bool server_socket::open(const char* addr) { #ifndef ACL_WINDOWS if (strchr(addr, '/') != NULL) { fd_ = acl_unix_listen(addr, backlog_, block_ ? ACL_BLOCKING : ACL_NON_BLOCKING); unix_sock_ = true; ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); } else #endif fd_ = acl_inet_listen(addr, backlog_, block_ ? ACL_BLOCKING : ACL_NON_BLOCKING); if (fd_ == ACL_SOCKET_INVALID) { logger_error("listen %s error %s", addr, last_serror()); unix_sock_ = false; ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); return false; } if (unix_sock_) return true; // 之所以再用 getsockname 重新获得一些监听地址,主要是为了应对当输入的 addr // 为 ip:0 的情形,即当给定的地址中的端口为 0 时要求操作系统自动分配一个端口号 if (acl_getsockname(fd_, addr_, sizeof(addr_)) < 0) { logger_error("getsockname error: %s", acl_last_serror()); ACL_SAFE_STRNCPY(addr_, addr, sizeof(addr_)); } return true; }
int acl_sane_socketpair(int domain, int type, int protocol, ACL_SOCKET result[2]) { ACL_SOCKET listener = acl_inet_listen("127.0.0.1:0", 1, ACL_BLOCKING); char addr[64]; (void) domain; result[0] = ACL_SOCKET_INVALID; result[1] = ACL_SOCKET_INVALID; if (listener == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: listen error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); return -1; } acl_tcp_set_nodelay(listener); if (acl_getsockname(listener, addr, sizeof(addr)) < 0) { acl_msg_error("%s(%d), %s: getoskname error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(listener); return -1; } result[0] = acl_inet_connect(addr, ACL_BLOCKING, 0); if (result[0] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: connect %s error %s", __FILE__, __LINE__, __FUNCTION__, addr, acl_last_serror()); acl_socket_close(listener); return -1; } result[1] = acl_inet_accept(listener); acl_socket_close(listener); if (result[1] == ACL_SOCKET_INVALID) { acl_msg_error("%s(%d), %s: accept error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); acl_socket_close(result[0]); result[0] = ACL_SOCKET_INVALID; return -1; } acl_tcp_set_nodelay(result[0]); acl_tcp_set_nodelay(result[1]); return 0; }
ACL_VSTREAM *acl_vstream_listen_ex(const char *addr, int qlen, int block_mode, int io_bufsize, int io_timeout) { const char *myname = "acl_vstream_listen_ex"; ACL_SOCKET listenfd; struct sockaddr_in local; ACL_VSTREAM *listen_stream; int len; if (addr == 0 || *addr == 0 || qlen <= 0) { acl_msg_error("%s: input invalid", myname); return NULL; } #ifdef ACL_UNIX /* this maybe unix addr, such as '/home/test/listen.sock' */ if (strchr(addr, '/') != NULL) { listenfd = acl_unix_listen(addr, qlen, 0); if (listenfd == ACL_SOCKET_INVALID) return NULL; acl_non_blocking(listenfd, block_mode); listen_stream = acl_vstream_fdopen(listenfd, ACL_VSTREAM_FLAG_RW, io_bufsize, io_timeout, ACL_VSTREAM_TYPE_LISTEN_UNIX); if (listen_stream == NULL) { acl_socket_close(listenfd); acl_msg_error("%s: open vstream error, addr(%s)", myname, addr); return NULL; } acl_vstream_set_local(listen_stream, addr); sprintf(listen_stream->errbuf, "+OK"); return (listen_stream); } #endif /* addr such as '192.168.0.1:80' */ listenfd = acl_inet_listen(addr, qlen, block_mode); if (listenfd == ACL_SOCKET_INVALID) { acl_msg_error("%s: listen addr(%s) error(%s)", myname, addr, acl_last_serror()); return NULL; } listen_stream = acl_vstream_fdopen(listenfd, ACL_VSTREAM_FLAG_RW, io_bufsize, io_timeout, ACL_VSTREAM_TYPE_LISTEN_INET); if (listen_stream == NULL) { acl_socket_close(listenfd); acl_msg_error("%s: open vstream error addr(%s)", myname, addr); return NULL; } memset(&local, 0, sizeof(local)); len = (int) sizeof(struct sockaddr); if (getsockname(listenfd, (struct sockaddr*) &local, (socklen_t *) &len) < 0) { acl_msg_warn("%s: getsockname error(%s) for sock(%d)", myname, acl_last_serror(), listenfd); acl_vstream_set_local(listen_stream, addr); } else { char ip[32], buf[64]; int port; acl_inet_ntoa(local.sin_addr, ip, sizeof(ip)); port = ntohs(local.sin_port); snprintf(buf, sizeof(buf), "%s:%d", ip, port); acl_vstream_set_local(listen_stream, buf); } sprintf(listen_stream->errbuf, "+OK"); return listen_stream; }