#include #include #include #include #include #include #include #include #include void my_perror(const char* msg) { cerr << msg << ": " << strerror(errno) << " (" << errno << ")" << endl; } void waitSelect(int fd) { fd_set wrfds; FD_ZERO(&wrfds); FD_SET(fd, &wrfds); int r = ::select(fd + 1, NULL, &wrfds, NULL, NULL); cerr << "select = " << r << endl; cerr << "fd_isset = " << (int)(FD_ISSET(fd, &wrfds)) << endl; if (r <= 0) { my_perror("select"); exit(1); } } int main(int argc, char* argv[]) { int fd, r; if (argc < 2) { cerr << "Usage: connect [nonblock]" << endl; exit(2); } bool nonblock = (argc > 2); int port = ::atoi(argv[1]); while (1) { cerr << "sleep..." << endl; sleep(1); cerr << "starting connect" << endl; fd = ::socket(PF_INET, SOCK_STREAM, 0); if (fd == -1) { my_perror("socket"); exit(1); } cerr << "fd = " << fd << endl; if (nonblock) { ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK); } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(port); ::memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); if (::connect(fd, (sockaddr*)&sin, sizeof(sin)) != 0) { if (errno != EINPROGRESS) { my_perror("connect"); ::close(fd); continue; } my_perror("connect"); cerr << "waiting for connect..." << endl; waitSelect(fd); cerr << "waiting over" << endl; int sockError = 0; socklen_t sockErrorLen = sizeof(sockError); if (::getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockError, &sockErrorLen) == -1) { my_perror("getsockopt SO_ERROR"); exit(1); } if (sockError != 0) { cerr << "connect: " << strerror(sockError) << " (" << sockError << ")" << endl; ::close(fd); continue; } cerr << "connected" << endl; } else { cerr << "connected straight away" << endl; } ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) & ~O_NONBLOCK); while (1) { char buffer[256]; r = ::read(fd, buffer, sizeof(buffer)); cerr << "read = " << r << endl; // blocking read from socket if (r <= 0) break; } ::close(fd); if (r < 0) my_perror("read"); else cerr << "EOF" << endl; } }