здравствуйте, есть код простейшего эхо-сервера:
#ifndef MAX_BUF
#define MAX_BUF 1024
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sig_usr;
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGKILL);
sigaddset(&set, SIGCHLD);
act.sa_mask = set;
sigaction(SIGKILL, &act, 0);
sigaction(SIGCHLD, &act, 0);
//устанавливаем параметры серверного сокета
struct sockaddr_in server;
char client_message[MAX_BUF];
std::fill(client_message,
client_message + std::size(client_message) - 1,
0);
int listen_desc = ::socket(AF_INET , SOCK_STREAM , 0);
if (listen_desc == -1) {
std::cout << "Could not create socket\n";
::exit(EXIT_FAILURE);
}
setnonblock(listen_desc);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 1600 );
int yes = 1;
::setsockopt(listen_desc, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if( ::bind(listen_desc,(struct sockaddr *)&server , sizeof(server)) < 0) {
//print the error message
std::cout << "error in bind\n";
::exit(EXIT_FAILURE);
}
::listen(listen_desc , 5);
//клиентский сокет
int cs{};
// create epoll instance
int epfd;
epfd = epoll_create(5);
if (epfd == -1) {
std::cout << "error in epoll_create\n";
}
struct epoll_event evlist[count];
struct epoll_event ev;
ev.data.fd = listen_desc;
ev.events = EPOLLIN | EPOLLET;
if(::epoll_ctl (epfd, EPOLL_CTL_ADD, listen_desc, &ev) == -1) {
std::cout << "error in epoll_ctl\n";
}
while (/*strstr(request, "close") == NULL*/true) {
int ready = epoll_wait(epfd, evlist, count, -1);
if(ready == -1) {
std::cout << "interrupt syscall epoll_wait was occured\n";
if(errno == EINTR) {
std::cout << "continue epoll_wait\n";
continue;
}
std::cout<< "error in epoll_wait and exit\n";
::exit(1);
}
//добавляем новый дескриптор
for(auto i=0;i<ready; ++i) {
if ((evlist[i].events & EPOLLERR) ||
(evlist[i].events & EPOLLHUP) ||
(!(evlist[i].events & EPOLLIN)))
{
//ошибка в epoll или сокет не готов читать
std::cout << "epoll error\n";
::close (evlist[i].data.fd);
continue;
}
//если событие пришло из слушающего дескриптора
if(evlist[i].data.fd == listen_desc) {
struct sockaddr_in in_addr;
socklen_t in_len;
in_len = sizeof(in_addr);
// cs = ::accept(listen_desc, (struct sockaddr *) &client,
// (socklen_t*)&c);
cs = ::accept (listen_desc, (sockaddr*)&in_addr, &in_len);
if(cs == -1){
std::cout<<"error in accept on listen descriptor\n";
continue;
}
//добавляем полученный дескриптор в ожидающие
setnonblock(cs);
ev.data.fd = cs;
ev.events = EPOLLIN | EPOLLET;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, cs, &ev) == -1) {
std::cout << "error in add descriptor to epoll\n";
continue;
}
} else {
char buf[MAX_BUF];
::memset(buf, 0, sizeof(buf));
int byte_count = ::read(evlist[i].data.fd, buf, MAX_BUF);
if (byte_count == -1) {
std::cout << "error in read\n";
continue;
}
//если клиент закрыл соединение
else if(byte_count == 0) {
if (epoll_ctl(epfd, EPOLL_CTL_DEL, evlist[i].data.fd, &ev) == -1) {
std::cout << "error in delete descriptor from epoll\n";
continue;
}
std::cout << "client with descriptor "
<< evlist[i].data.fd
<< " close connection\n";
::close(evlist[i].data.fd);
} else {
//печатаем на экран и отправляем обратно пришедшее сообщение
std::fill(client_message,
client_message + std::size(client_message) - 1,
0);
::memcpy(client_message, buf, byte_count);
std::cout << client_message;
char response[] =
// Заголовок.
"HTTP/1.1 200 OK \n Content-Type: text/xml;charset=utf-8 \n Content-Length: 256"
// Тело HTML страницы.
"<!doctype html>"
"<html lang=\"en\">"
"<head>"
"<meta charset=\"UTF-8\">"
"<title>Document</title>"
"</head>"
"<body>"
"ваш запрос: <strong>1</strong>"
"</body>"
"</html>\n";
if (::send(evlist[i].data.fd, response/*client_message*/, sizeof(response)/*byte_count*/, 0) == -1) {
std::cout << "error in send\n";
}
// //std::cout << buf;
// if (::send(evlist[i].data.fd, /*response*/client_message, /*sizeof(buf)*/byte_count, 0) == -1) {
// std::cout << "error in send\n";
// }
}
}
}
}
#else
#endif
з.ы. исправил кое-что, теперь сокеты неблокирующие, возвращается html-страница как ответ