У меня возникла проблема с сервером tcp. Я хотел бы слушать несколько портов, чтобы отвечать на запросы клиентов. Это должно быть своего рода событие. Каждый порт указывает другой тип ответа. Я много читал о epoll, опросе, выборе или многопоточности. Я пытался работать с большим количеством примеров из таких книг, как Unix Network Programming. Но, вероятно, мне нужны несколько ключевых слов триггера. Как я мог начать правильно?Linux TCP Server - прослушивание нескольких портов в C++
Надеюсь, мои вопросы легко понять. Цените каждый ответ!
сужать его вниз ЕСТЬ МОЯ ИДЕЯ ... Я начал думать об этом:
Если я есть «Диспетчер сервера» с большим количеством сервера, я могу сделать это следующим образом?
CreateSockets (ServerList); CheckSockets (SocketList, master_set);
В диспетчере сервера: 1) для цикла, чтобы создать все сокеты сервера (функции: гнездо/setsockopt/IOCTL/привязывать/слушать)
void CreateSockets(map<int,ServerType> ServerList)
{
fd_set master_set;
map<int,ServerType>::iterator it;
map<int,int> SocketList;
for (it= ServerList.begin();it!= ServerList.end();it++)
{
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sd < 0)
{
perror("socket() failed");
exit(-1);
}
rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on));
if (rc < 0)
{
perror("setsockopt() failed");
close(listen_sd);
exit(-1);
}
rc = ioctl(listen_sd, FIONBIO, (char *)&on);
if (rc < 0)
{
perror("ioctl() failed");
close(listen_sd);
exit(-1);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = ((*it).second->Port);
rc = bind(listen_sd,(struct sockaddr *)&addr, sizeof(addr));
if (rc < 0)
{
perror("bind() failed");
close(listen_sd);
exit(-1);
}
rc = listen(listen_sd, 32);
if (rc < 0)
{
perror("listen() failed");
close(listen_sd);
exit(-1);
}
SocketList.insert(make_pair(((*it).second->Port),listen_sd));
FD_ZERO(&master_set);
max_sd = listen_sd;
FD_SET(listen_sd, &master_set);
}
}
Следующая: 2) Некоторые, как ждать, пока некоторые события в диспетчере сервера (Select со списком гнездовых дескрипторов)
void CheckSockets(map<int,int> SocketList, fd_set master_set)
{
fd_set working_set;
do
{
memcpy(&working_set, &master_set, sizeof(master_set));
ready_descriptors = select(max_sd + 1, &working_set, NULL, NULL, NULL);
if (ready_descriptors >0)
{
desc_ready = rc;
for (i=0; i <= max_sd && desc_ready > 0; ++i)
{
if (FD_ISSET(i, &working_set))
{
desc_ready -= 1;
if (i == listen_sd)
{
do
{
new_sd = accept(listen_sd, NULL, NULL);
if (new_sd < 0)
{
//error
}
FD_SET(new_sd, &master_set);
if (new_sd > max_sd)
max_sd = new_sd;
} while (new_sd != -1);
}
else
{
do
{
//Go into server and recv and send (Input Parameter = i)
CheckServer(i);
} while (TRUE);
}
}
}
}
else {endserver=true;}
}while(endserver=true;)
}
3) Заходим на сервер и обработать вопрос (RECV/посыла) ????
void CheckServer(int sd)
{
rc = recv(sd, buffer, sizeof(buffer), 0);
//some stuff in between
rc = send(i, buffer, len, 0);
}
Могло ли это работать?
Некоторые детали используются и заменяются кодом источника неблокирующего ввода-вывода IBM.
благодарим за вашу помощь. Я смог что-то сделать, НО еще одно не работает.
То, что я сделал до сих пор:
1) consrtuctor отдельного сервера не включает в себя операции сокета. 2) Я могу вернуть идентификатор сокета и сохранить его в диспетчере серверов. 3) Менеджер имеет цикл for, который содержит команду select для проверки любого события в сокетах. 4) если что-то произойдет, все затронутые сокеты будут последовательно воспроизводиться.
Моя проблема:
Он отлично работает, если я всегда подключать и отключать во время я запрашивая данные с сервера. Когда мой клиент настроен таким образом, что соединение будет удерживаться, все блокируется, так как мой код ждет разъединения.
Вот фрагменты кода для каждой части:
1)
Server::Server()
{
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
ret = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on));
ret = ioctl(listen_sd, FIONBIO, (char *)&on);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(Server_Port);
ret = bind(listen_sd,(struct sockaddr *)&addr, sizeof(addr));
ret = listen(listen_sd, 32);
Socket = listen_sd;
}
2)
Socket= new_Server->GetSocket();
SocketList.insert(make_pair(Socket,new_Server->ServerID));
3)
while (TRUE)
{
FD_ZERO(&working_set);
for (i=0;i < max_conn;i++)
{
if (SocketArray[i] >= 0) {FD_SET(SocketArray[i], &working_set);}
}
ret = select(max_sd+1, &working_set, NULL, NULL, NULL);
desc_ready= ret;
for (i=0; i <= max_sd && desc_ready > 0; ++i)
{
if (FD_ISSET(i, &working_set)) //jeder Peer der was hat
{
desc_ready -= 1;
//delete all loops to get the correct object
(Server).second->DoEvent(i);
}
}
}
4)
Я просто удаляю обработку ошибок dor listen/bind и т. Д., Чтобы просто сократить код здесь ... Первоначально он там.
Этот вопрос слишком широк, пожалуйста, сузите его к чему-то, на что можно ответить. – Mgetz
вы проверили [Beej's Guide to Network Programming] (http://beej.us/guide/bgnet/) уже? который имеет все основы (в стиле c, хотя). – codeling
Взгляните на шаблон реактора ... – Sambuca