Created
July 24, 2015 01:14
-
-
Save elvinio/367648aeb0862d1aa792 to your computer and use it in GitHub Desktop.
Code shows how to listen on a tcp socket in C++ and accept a connection
This file contains hidden or 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
static struct sockaddr_in sa; | |
int listenCount = 0; | |
static const MAX_FD = 2048; | |
static struct pollfd listenFds[MAX_FD]; | |
int main(int argc, char** argv){ | |
int timeout = 15000; | |
listenPort(16000); | |
while(1){ | |
int val = poll((struct pollfd *)$listenFds, listenCount, timeout); | |
if(val > 0){ | |
socklen_t sz = sizeof(sa); | |
for(int i=0; i < listenCount; i++){ | |
if(listenFds[i].revents & POLLIN){ | |
int sock = listenFds[i].fd; | |
int port; | |
int socket = accept(sock, (struct sockaddr *)&sa, &sz); | |
setNoDelaySocket(socket); | |
setNonBlockingSocket(socket); | |
} | |
} | |
} | |
} | |
void listenPort(const int port){ | |
int s, reuse = 1; | |
// Create the socket | |
s = socket(AF_INET, SOCK_STREAM, 0); | |
if(s<0){ | |
cout << "Failed to create socket"; | |
return; | |
} | |
// Allows socket to be resued when it is in TIME_WAIT state | |
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)); | |
// Set non-blocking | |
setNonBlocking(s); | |
// Bind the socket to the port. | |
memset(&sa, 0, sizeof(sa)); | |
// Set it to Address Family (Internet Protocol) | |
sa.sin_family.s_addr = AF_INET; | |
// Binding it to all interfaces on the server | |
sa.sin_addr.s_addr = htonl(INADDR_ANY); | |
// Binding on this port | |
sa.sin_port = htons(port); | |
int result = bind(s, (struct sockaddr *)&sa, sizeof(sa)); | |
// If another socket is using that port, the program will fail to bind. | |
if(result < 0){ | |
cout << "Failed to bind on port " << port << ", error: " << result; | |
return; | |
} | |
listenFds[listenCount].fd = s; | |
listenFds[listenCount].events = POLLIN; | |
listenFds[listenCount].revents = 0; | |
listenCount++; | |
// Set the port to listen | |
// 64 is the number of backlog for uncompleted connections (SYN_RECV) | |
int listenResult = listen(s, 64); | |
if(listenResult < 0){ | |
cout << "Failed to listen on port " << port; | |
} | |
} | |
void setNoDelay(int s){ | |
const int nope = 1; | |
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&nope, sizeof(nope)); | |
} | |
void setNonBlocking(int s){ | |
// fcntl is used instead of ioctl | |
// flags &= ~O_NONBLOCK; unsets the non-blocking flag | |
int flags = 0; | |
if((flags = fcntl(s, F_GETFL, 0))<0){ | |
cout << "Failed to get fcntl flags"; | |
} | |
if(fnctl(s, F_SETFL, flags | O_NONBLOCK) < 0){ | |
cout << "Failed to set non-blocking flag"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment