/* Set TCP keep alive option to detect dead peers. The interval option * is only used for Linux as we are using Linux-specific APIs to set * the probe send time, interval, and count. */ int anetKeepAlive(char *err, int fd, int interval) { int val = 1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) { anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); return ANET_ERR; } #ifdef __linux__ /* Default settings are more or less garbage, with the keepalive time * set to 7200 by default on Linux. Modify settings to make the feature * actually useful. */ /* Send first probe after interval. */ val = interval; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno)); return ANET_ERR; } /* Send next probes after the specified interval. Note that we set the * delay as interval / 3, as we send three probes before detecting * an error (see the next setsockopt call). */ val = interval/3; if (val == 0) val = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno)); return ANET_ERR; } /* Consider the socket in error state after three we send three ACK * probes without getting a reply. */ val = 3; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); return ANET_ERR; } #else ((void) interval); /* Avoid unused var warning for non Linux systems. */ #endif return ANET_OK; }
/* anet设置非阻塞的方法 */ int anetNonBlock(char *err, int fd) { int flags; /* Set the socket non-blocking. * Note that fcntl(2) for F_GETFL and F_SETFL can't be * interrupted by a signal. */ if ((flags = fcntl(fd, F_GETFL)) == -1) { anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); return ANET_ERR; } //调用fcntl方法设置非阻塞方法 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetV6Only(char *err, int s) { int yes = 1; if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) { anetSetError(err, "setsockopt: %s", strerror(errno)); close(s); return ANET_ERR; } return ANET_OK; }
int anetTcpKeepAlive(char *err, int fd) { int yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
int anetSetSendBuffer(char *err, int fd, int buffsize) { if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) { anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetSetReuseAddr(char*err,int fd) { int yes=1; if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))<0){ anetSetError(err,"setsockopt:%s\n",strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetSetTcpNoDelay(char *err, int fd, int val) { if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) { anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetCreateSocket(char *err, int domain) { int s, on = 1; if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { #ifdef _WIN32 errno = WSAGetLastError(); #endif anetSetError(err, "creating socket: %s", strerror(errno)); return ANET_ERR; } /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); return ANET_ERR; } return s; }
int anetTcpNoDelay(char *err, int fd) { int yes = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt TCP_NODELAY: %s\n", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetSetReuseAddr(char *err, int fd) { int yes = 1; /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetCreateSocket(char *err, int domain) { int rfd; int on = 1; if ((rfd = socket(domain, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { errno = WSAGetLastError(); anetSetError(err, "create socket error: %d\n", errno); return ANET_ERR; } /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ if (setsockopt(rfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == SOCKET_ERROR) { errno = WSAGetLastError(); anetSetError(err, "setsockopt SO_REUSEADDR: %d\n", errno); return ANET_ERR; } return rfd; }
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) { int s, rv; char _port[6]; /* strlen("65535"); */ struct addrinfo hints, *servinfo, *p; snprintf(_port,6,"%d",port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { anetSetError(err, "%s", gai_strerror(rv)); return ANET_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; /* if we set err then goto cleanup, otherwise next */ if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK) goto error; if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) goto end; close(s); continue; } /* break with the socket */ goto end; } if (p == NULL) { anetSetError(err, "creating socket: %s", strerror(errno)); goto error; } error: s = ANET_ERR; end: freeaddrinfo(servinfo); return s; }
int anetSetBlock(char*err,int fd,int flag) { int flags; if((flags=fcntl(fd,F_GETFL))==-1){ anetSetError(err,"fcntl:%s\n",strerror(errno)); return ANET_ERR; } if(flag){ flags|=O_NONBLOCK; }else{ flags|=~O_NONBLOCK; } if((fcntl(fd,F_SETFL,flags))==-1){ anetSetError(err,"fcntl:%s\n",strerror(errno)); return ANET_ERR; } return ANET_OK; }
/* Set the socket send timeout (SO_SNDTIMEO socket option) to the specified * number of milliseconds, or disable it if the 'ms' argument is zero. */ int anetSendTimeout(char *err, int fd, long long ms) { struct timeval tv; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { anetSetError(err, "setsockopt SO_SNDTIMEO: %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) { int s, on = 1; struct sockaddr_in sa; if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { anetSetError(err, "creating socket: %s\n", strerror(errno)); return ANET_ERR; } /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); sa.sin_family = AF_INET; sa.sin_port = htons(port); if (inet_aton(addr, &sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(addr); if (he == NULL) { anetSetError(err, "can't resolve: %s\n", addr); close(s); return ANET_ERR; } memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); } if (flags & ANET_CONNECT_NONBLOCK) { if (anetNonBlock(err,s) != ANET_OK) return ANET_ERR; } if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) return s; anetSetError(err, "connect: %s\n", strerror(errno)); close(s); return ANET_ERR; } return s; }
static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog) { int s, rv; char _port[6]; /* strlen("65535") */ struct addrinfo hints, *servinfo, *p; snprintf(_port,6,"%d",port); memset(&hints,0,sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; /* No effect if bindaddr != NULL */ if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) { anetSetError(err, "%s", gai_strerror(rv)); return ANET_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error; #ifdef _WIN32 if (anetSetExclusiveAddr(err,s) == ANET_ERR) goto error; #else if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; #endif if (anetListen(err,s,p->ai_addr,(socklen_t)p->ai_addrlen,backlog) == ANET_ERR) goto error; goto end; } if (p == NULL) { anetSetError(err, "unable to bind socket"); goto error; } error: s = ANET_ERR; end: freeaddrinfo(servinfo); return s; }
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) { int s; struct sockaddr_in sa; unsigned long inAddress; if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) return ANET_ERR; sa.sin_family = AF_INET; sa.sin_port = htons((u_short)port); inAddress = inet_addr(addr); if (inAddress == INADDR_NONE || inAddress == INADDR_ANY) { struct hostent *he; he = gethostbyname(addr); if (he == NULL) { anetSetError(err, "can't resolve: %s\n", addr); closesocket(s); return ANET_ERR; } memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); } else { sa.sin_addr.s_addr = inAddress; } if (aeWinSocketConnect(s, (struct sockaddr*)&sa, sizeof(sa)) == SOCKET_ERROR) { if ((errno == WSAEWOULDBLOCK || errno == WSA_IO_PENDING)) errno = EINPROGRESS; if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) { return s; } anetSetError(err, "connect: %d\n", errno); closesocket(s); return ANET_ERR; } return s; }
static int anetCreateSocket(char *err, int domain) { int s, on = 1; int accept_delay = 1; if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { anetSetError(err, "creating socket: %s", strerror(errno)); return ANET_ERR; } /* Make sure connection-intensive things like the redis benckmark * will be able to close/open sockets a zillion of times */ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); return ANET_ERR; } setsockopt(s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &accept_delay, sizeof(accept_delay)); // setsockopt(s, IPPROTO_TCP, SOL_SOCKET, SO_SNDBUF, sizeof(accept_delay)); // setsockopt(s, IPPROTO_TCP, SOL_SOCKET, SO_RCVBUF); return s; }
static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) { int s; struct sockaddr_in sa; if ((s = anetCreateSocket(err,AF_INET)) == ANET_ERR) return ANET_ERR; sa.sin_family = AF_INET; sa.sin_port = htons(port); if (inet_aton(addr, &sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(addr); if (he == NULL) { anetSetError(err, "can't resolve: %s", addr); close(s); return ANET_ERR; } memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); } if (flags & ANET_CONNECT_NONBLOCK) { if (anetNonBlock(err,s) != ANET_OK) return ANET_ERR; } if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) return s; anetSetError(err, "connect: %s", strerror(errno)); close(s); return ANET_ERR; } return s; }
int anetSetBlock(char *err, int fd, int non_block) { int flags; /* Set the socket blocking (if non_block is zero) or non-blocking. * Note that fcntl(2) for F_GETFL and F_SETFL can't be * interrupted by a signal. */ if ((flags = fcntl(fd, F_GETFL)) == -1) { anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); return ANET_ERR; } if (non_block) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) { anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetTcpGenericConnect(char*err,char*ip,int port,int flags) { int s,on=1; struct sockaddr_in sa; if((s=socket(AF_INET,SOCK_STREAM,0))==-1){ anetSetError(err,"create socket:%s\n",strerror(errno)); return ANET_ERR; } setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); sa.sin_family=AF_INET; sa.sin_port=htons(port); if(inet_aton(ip,&sa.sin_addr)==0){ struct hostent*he; he=gethostbyname(ip); if(he==NULL){ anetSetError(err,"Can't resolver:%s\n",ip); close(s); return ANET_ERR; } memcpy(&sa.sin_addr,he->h_addr,sizeof(struct in_addr)); } if(flags&ANET_CONNECT_NONBLOCK){ if(anetNonBlock(err,s)!=ANET_OK) return ANET_ERR; } if(connect(s,(struct sockaddr*)&sa,sizeof(sa))==-1){ if(errno==EINPROGRESS&&flags&ANET_CONNECT_NONBLOCK) return s;//让它继续完成connect anetSetError(err,"Connect:%s\n",strerror(errno)); close(s); return ANET_ERR; } return s; }
int anetNonBlock(char *err, int fd) { /* Set the socket nonblocking on Windows * If iMode = 0, blocking is enabled; * If iMode != 0, non-blocking mode is enabled.*/ u_long iMode = 1; if (ioctlsocket((SOCKET)fd, FIONBIO, &iMode) == SOCKET_ERROR) { errno = WSAGetLastError(); anetSetError(err, "ioctlsocket(FIONBIO): %d\n", errno); return ANET_ERR; }; return ANET_OK; }
/** * set the socket send buff */ int anetSetSendBuffer(char *err, int fd, int buffsize) { /** * SOL_SOCKET has been defined in socket.h on Mac with value of 0xffff * SO_SNDBUF has been defined in socket.h on Mac with value of 0x1001 * the setsockopt function will set the send buff size to buffsize */ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) { anetSetError(err, "setsockopt SO_SNDBUF: %s\n", strerror(errno)); return ANET_ERR; } return ANET_OK; }
/** * set the tcp to keep alive */ int anetTcpKeepAlive(char *err, int fd) { int yes = 1; /** * SOL_SOCKET has been defined in socket.h on Mac with value of 0xffff * SO_KEEPALIVE has been defined in socket.h on Mac with value of 0x0008 * the following function will set tcp to keep alive. */ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt SO_KEEPALIVE: %s\n", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) { if (bind(s,sa,len) == -1) { #ifdef _WIN32 errno = WSAGetLastError(); #endif anetSetError(err, "bind: %s", strerror(errno)); close(s); return ANET_ERR; } /* Use a backlog of 512 entries. We pass 511 to the listen() call because * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); * which will thus give us a backlog of 512 entries */ if (listen(s, 511) == -1) { #ifdef _WIN32 errno = WSAGetLastError(); #endif anetSetError(err, "listen: %s", strerror(errno)); close(s); return ANET_ERR; } return ANET_OK; }
int anetTcpServer(char *err, int port, char *bindaddr) { int s, on = 1; struct sockaddr_in sa; if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { anetSetError(err, "socket: %s\n", strerror(errno)); return ANET_ERR; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { anetSetError(err, "setsockopt SO_REUSEADDR: %s\n", strerror(errno)); close(s); return ANET_ERR; } memset(&sa,0,sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(INADDR_ANY); if (bindaddr) { if (inet_aton(bindaddr, &sa.sin_addr) == 0) { anetSetError(err, "Invalid bind address\n"); close(s); return ANET_ERR; } } if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { anetSetError(err, "bind: %s\n", strerror(errno)); close(s); return ANET_ERR; } if (listen(s, 511) == -1) { /* the magic 511 constant is from nginx */ anetSetError(err, "listen: %s\n", strerror(errno)); close(s); return ANET_ERR; } return s; }
/** * set socket nodelay */ int anetTcpNoDelay(char *err, int fd) { int yes = 1; /** * int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len); * IPPROTO_TCP has been defined in in.h on Mac with value of 6 * TCP_NODELAY has been defined in tcp.h on Mac with value of 0x01 */ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { anetSetError(err, "setsockopt TCP_NODELAY: %s\n", strerror(errno)); return ANET_ERR; } return ANET_OK; }
static int anetCreateSocket(char *err, int domain) { int s; if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { anetSetError(err, "creating socket: %s", strerror(errno)); return ANET_ERR; } /* Make sure connection-intensive things like the redis benchmark * will be able to close/open sockets a zillion of times */ if (anetSetReuseAddr(err,s) == ANET_ERR) { close(s); return ANET_ERR; } return s; }
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { int fd; while(1) { fd = accept(s,sa,len); if (fd == -1) { if (errno == EINTR) { continue; } else { anetSetError(err, "accept: %s", strerror(errno)); } } break; } return fd; }
static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { SOCKET fd; while(1) { fd = aeWinAccept((SOCKET)s,sa,len); if (fd == SOCKET_ERROR) { if (errno == WSAEINTR) continue; else { anetSetError(err, "accept: %s\n", strerror(errno)); return ANET_ERR; } } break; } return (int)fd; }