Skip to content

Instantly share code, notes, and snippets.

@elvinio
Last active August 29, 2015 14:25
Show Gist options
  • Save elvinio/2fe86077f3c63abee322 to your computer and use it in GitHub Desktop.
Save elvinio/2fe86077f3c63abee322 to your computer and use it in GitHub Desktop.
Establishing a TCP connection
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