Created
February 11, 2019 16:04
-
-
Save devendranaga/293137c98ba4e913cfb242ba1e0cb932 to your computer and use it in GitHub Desktop.
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
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <unistd.h> | |
#include <functional> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
struct callback_data { | |
int fd; | |
void *ptr; | |
std::function<void(callback_data)> cb; | |
}; | |
class select_call { | |
private: | |
fd_set allfd; | |
int maxfd; | |
std::vector<callback_data> list; | |
public: | |
select_call() { | |
FD_ZERO(&allfd); | |
maxfd = 0; | |
} | |
~select_call() { } | |
void add_fd(callback_data cd) | |
{ | |
FD_SET(cd.fd, &allfd); | |
list.push_back(cd); | |
if (cd.fd > maxfd) | |
maxfd = cd.fd; | |
std::cout << "add fd " << cd.fd << std::endl; | |
} | |
void rem_fd(int fd) | |
{ | |
std::vector<callback_data>::iterator it; | |
for (it = list.begin(); it != list.end(); it ++) { | |
if (it->fd == fd) { | |
break; | |
} | |
} | |
if (it != list.end()) { | |
FD_CLR(it->fd, &allfd); | |
std::cout << "rem fd " << it->fd << std::endl; | |
list.erase(it); | |
} | |
} | |
void run() | |
{ | |
while (1) { | |
int ret; | |
fd_set rd = allfd; | |
ret = select(maxfd + 1, &rd, NULL, NULL, NULL); | |
if (ret > 0) { | |
std::vector<callback_data>::const_iterator it; | |
for (it = list.begin(); it != list.end(); it ++) { | |
if (FD_ISSET(it->fd, &rd)) { | |
it->cb(*it); | |
break; | |
} | |
} | |
} | |
} | |
} | |
}; | |
class tcp_server { | |
private: | |
int fd; | |
struct sockaddr_in serv; | |
select_call c; | |
public: | |
tcp_server(std::string ip, int port) | |
{ | |
fd = socket(AF_INET, SOCK_STREAM, 0); | |
if (fd < 0) { | |
perror(""); | |
return; | |
} | |
int raddr = 1; | |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &raddr, sizeof(raddr)); | |
serv.sin_addr.s_addr = inet_addr(ip.c_str()); | |
serv.sin_port = htons(port); | |
serv.sin_family = AF_INET; | |
int ret; | |
ret = bind(fd, (struct sockaddr *)(&serv), sizeof(serv)); | |
if (ret < 0) { | |
perror(""); | |
close(fd); | |
return; | |
} | |
ret = listen(fd, 4); | |
if (ret < 0) { | |
perror(""); | |
close(fd); | |
return; | |
} | |
callback_data cd; | |
cd.ptr = this; | |
cd.fd = fd; | |
cd.cb = std::bind(&tcp_server::accept_call, this, std::placeholders::_1); | |
c.add_fd(cd); | |
} | |
void accept_call(callback_data ptr) | |
{ | |
int cl_fd; | |
struct sockaddr_in dest; | |
socklen_t dest_len = sizeof(struct sockaddr_in); | |
cl_fd = accept(fd, (struct sockaddr *)&dest, &dest_len); | |
if (cl_fd < 0) { | |
perror(""); | |
return; | |
} | |
callback_data cd; | |
cd.ptr = this; | |
cd.fd = cl_fd; | |
cd.cb = std::bind(&tcp_server::recv_call, this, std::placeholders::_1); | |
c.add_fd(cd); | |
} | |
void recv_call(callback_data ptr) | |
{ | |
char data[102]; | |
int ret; | |
ret = recv(ptr.fd, data, sizeof(data), 0); | |
if (ret <= 0) { | |
c.rem_fd(ptr.fd); | |
return; | |
} | |
std::cout << "data " << data << std::endl; | |
} | |
void run() | |
{ | |
c.run(); | |
} | |
}; | |
int main() | |
{ | |
tcp_server server("127.0.0.1", 1244); | |
server.run(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment