Last active
August 29, 2015 14:25
-
-
Save elvinio/2fe86077f3c63abee322 to your computer and use it in GitHub Desktop.
Establishing a TCP connection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int connect(const std::string &host, const int port, const int timeout){ | |
struct sockaddr_in sa = {0}; | |
int socket; | |
// Create and populate the connect address structure | |
sa.sin_family = AF_INET; | |
// The htons() function converts the unsigned short integer hostshort | |
// from host byte order to network byte order | |
// On the i80x86 the host byte order is least significant byte first, | |
// whereas the network byte order, as used on the Internet, is the | |
// most significant byte first | |
sa.sin_port = htons(port); | |
inet_pton(AF_INET, host.c_str(), &(sa.sin_addr)); | |
// Not an IP address - attempt to resolve as a hostname instead | |
if (sa.sin_addr.s_addr == (in_addr_t)(-1)){ | |
struct hostent *hostentry; | |
hostentry = gethostbyname(host.c_str()); | |
if(!hostentry){ | |
std::ostringstream ss; | |
ss << "connect: gethostybname error: " << hstrerror(h_errno); | |
cout << ss; | |
return -1; | |
} | |
if (hostentry->h_addrtype != AF_INET){ | |
cout << "connect: h_addrtype == " << hostentry->h_addrtype | |
<< ", only support " << AF_INET << " (AF_INET); | |
} | |
if (!hostentry->h_addr_list[0]){ | |
cout << "connect: no addresses found"; | |
return -1; | |
} | |
sa.sin_addr = *(struct in_addr *)hostentry->h_addr_list[0]; | |
} | |
socket = socket(AF_INET, SOCK_STREAM, 0); | |
if(socket < 0){ | |
cout << "connect: failed to create socket " << socket; | |
return -1; | |
} | |
setNonBlocking(socket); | |
setNoDelay(socket); | |
setBuffer(socket, 2048); | |
// Doing a non-blocking connect, expecting to get EINPROGRESS | |
int result; | |
if((result = connect(socket, (struct sockaddr *)&sa, sizeof(sa))) != 0 && errno != EINPROGRESS){ | |
cout << "connect: failed to connect " << result; | |
if(socket>=0) ::close(socket); | |
return -1; | |
} | |
// Poll once to confirm connection is established | |
struct pollfd fds[1]; | |
if(timeout <= 0 || timeout > 30000) timeout = 30000; | |
result = 0; | |
fds[0].fd = socket; | |
fds[0].revents = 0; | |
fds[0].events = POLLIN | POLLOUT; | |
if((result = poll((struct pollfd *)&fds, 1, timeout)) == 0){ | |
::close(socket); | |
cout << "connect: Connection timeout " << timeout; | |
return -1; | |
} | |
else if(result < 0){ | |
::close(socket); | |
cout << "connect: poll failed, error " << errno; | |
return -1; | |
} | |
else if(fds[0].revents & POLLOUT) != 0){ | |
int error = 0; | |
int len = sizeof(error); | |
if(getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) < 0){ | |
::close(socket); | |
cout << "connect: Poll error " << error; | |
return -1; | |
} | |
else{ | |
cout << "connect: success, revents " << fds[0].revents; | |
result = 0; | |
} | |
} | |
if(result == -1){ | |
::close(socket); | |
return -1; | |
} | |
return socket; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment