Skip to content

Instantly share code, notes, and snippets.

@devendranaga
Created February 11, 2019 16:04
Show Gist options
  • Save devendranaga/293137c98ba4e913cfb242ba1e0cb932 to your computer and use it in GitHub Desktop.
Save devendranaga/293137c98ba4e913cfb242ba1e0cb932 to your computer and use it in GitHub Desktop.
#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