Skip to content

Instantly share code, notes, and snippets.

@elvinio
Created July 24, 2015 01:14
Show Gist options
  • Save elvinio/367648aeb0862d1aa792 to your computer and use it in GitHub Desktop.
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
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