1 #include <errno.h> 2 #include <string.h> 3 #include <fcntl.h> 4 #include <sys/socket.h> 5 #include <sys/types.h> 6 #include <sys/select.h> 7 #include <netinet/tcp.h> 8 #include <netinet/ip.h> 9 #include <arpa/inet.h> 10 #include <unistd.h> 11 #include <stdio.h> 12 13 int main(int argc, const char * argv[]) { 14 int sock = socket(PF_INET, SOCK_STREAM, 0); 15 if(sock == -1){ 16 const char* str = strerror(errno); 17 printf("socket: %s\n", str); 18 return -1; 19 } 20 21 int flags = fcntl(sock, F_GETFD, 0); 22 flags |= O_NONBLOCK; 23 fcntl(sock, F_SETFD, flags); 24 25 char ch = 1; 26 setsockopt(sock, IPPROTO_TP, TCP_NODELAY, &ch, sizeof(ch)); 27 int value = 1; 28 setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value)); 29 30 struct sockaddr_in addr = {0}; 31 addr.sin_family = AF_INET; 32 addr.sin_port = htons(8000); 33 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 34 35 int ret = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); 36 if(ret){ 37 int err = errno; 38 if(err != EINPROGRESS && err != EWOULDBLOCK){ 39 const char* str = strerror(errno); 40 printf("connect: %s\n", str); 41 //return -1; // 注释掉这里,后面 select 返回 1 42 } 43 44 int nfds = 0; 45 fd_set wset; 46 FD_ZERO(&wset); 47 FD_SET(sock, &wset); 48 nfds = sock + 1; 49 50 struct timeval timeout; 51 timeout.tv_sec = 1; 52 timeout.tv_usec = 0; 53 int n = select(nfds, 0, &wset, 0, &timeout); 54 if(n > 0){ 55 struct sockaddr in = {0}; 56 socklen_t len = sizeof(in); 57 int e = getpeername(sock, &in, &len); 58 if(e){ 59 int err = errno; 60 printf("getpeername: %s\n", strerror(err)); 61 } 62 } 63 64 } 65 66 return 0; 67 }
select 一个 "connection refused" 的 socket, socket 居然状态可写。。
原代码用 select 检查 socket 的可写状态来判断连接是否成功,IOS 版本的代码中没有对 connect 返回值做检查,才发现这个现象。。