Skip to content

Instantly share code, notes, and snippets.

@Shikugawa
Last active June 26, 2021 13:49
Show Gist options
  • Save Shikugawa/9fa3b14f154c8842bd59d714836f2e48 to your computer and use it in GitHub Desktop.
Save Shikugawa/9fa3b14f154c8842bd59d714836f2e48 to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <unordered_map>
void make_socket_nonblocking(int sock) {
int flags, s;
flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {
return;
}
flags |= O_NONBLOCK;
s = fcntl(sock, F_SETFL, flags);
if (s < 0) {
return;
}
}
int main(void) {
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(6113);
std::unordered_map<int, int> descriptor_map;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0) {
return -1;
}
if(bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
return -1;
}
if(listen(sock, 5) < 0) {
return -1;
}
int efd = epoll_create1(0);
if (efd < 0) {
return -1;
}
make_socket_nonblocking(efd);
struct epoll_event event;
struct epoll_event* events;
event.data.fd = sock;
event.events = EPOLLIN | EPOLLET;
int s = epoll_ctl(efd, EPOLL_CTL_ADD, sock, &event);
if (s < 0) {
return -1;
}
events = (epoll_event*)calloc(10, sizeof(epoll_event));
while (true) {
int n = epoll_wait(efd, events, 10, 500);
for (int i = 0; i < n; ++i) {
if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) {
fprintf (stderr, "epoll error. events=%u\n", events[i].events);
close (events[i].data.fd);
continue;
}
// サーバーソケットに対するイベントがあった時
if (events[i].data.fd == sock) {
std::cout << "in-server event" << std::endl;
struct sockaddr_in client_addr;
socklen_t size = sizeof(client_addr);
int client_sock = accept(sock, (struct sockaddr*)&client_addr, &size);
if (client_sock < 0) {
continue;
}
make_socket_nonblocking(client_sock);
event.data.fd = client_sock;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, client_sock, &event);
if (s < 0) {
continue;
}
continue;
}
if (descriptor_map.find(events[i].data.fd) != descriptor_map.end()) {
std::cout << "event from backend" << std::endl;
int recv_msg_size;
char buffer[256];
recv_msg_size = recv(events[i].data.fd, buffer, 256, 0);
if (recv_msg_size < 0) {
continue;
}
s = send(descriptor_map[events[i].data.fd], buffer, strlen(buffer), 0);
if (s < 0) {
continue;
}
close(events[i].data.fd);
close(descriptor_map[events[i].data.fd]);
descriptor_map.erase(events[i].data.fd);
continue;
}
std::cout << "event from client" << std::endl;
// クライアントソケットにイベントがあった時
int recv_msg_size;
char buffer[256];
recv_msg_size = recv(events[i].data.fd, buffer, 256, 0);
std::cout << recv_msg_size << std::endl;
if (recv_msg_size < 0) {
continue;
}
// send backend
struct sockaddr_in backend_addr;
backend_addr.sin_family = AF_INET;
backend_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
backend_addr.sin_port = htons(6110);
int backend_sock = socket(AF_INET, SOCK_STREAM, 0);
if (backend_sock < 0) {
continue;
}
int n = connect(backend_sock, (struct sockaddr*)&backend_addr, sizeof(struct sockaddr_in));
if (n < 0) {
continue;
}
make_socket_nonblocking(backend_sock);
std::string msg = "message";
n = send(backend_sock, msg.c_str(), msg.size(), 0);
if (n < 0) {
continue;
}
event.data.fd = backend_sock;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, backend_sock, &event);
if (s < 0) {
continue;
}
descriptor_map.emplace(backend_sock, events[i].data.fd);
}
}
close(sock);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment