Я делаю проект на C ++, который требует от сервера создания нового потока для обработки соединений каждый раз, когда accept () возвращает новый дескриптор сокета. Я использую команду select, чтобы решить, когда была предпринята попытка подключения, а также когда клиент отправил данные через вновь созданный клиентский сокет (который создает тот, который принимает accept). Таким образом, две функции и два выбора - один для опроса сокета, предназначенного для прослушивания соединений, один для опроса сокета, созданного при успешном новом соединении.
Поведение первого случая соответствует ожидаемому: FD_ISSET возвращает true для идентификатора моего прослушивающего сокета только при запросе соединения и ложно до следующей попытки подключения. Второй случай не работает, хотя код точно такой же с разными объектами fd_set и socket. Мне интересно, это происходит из-за сокета TCP? Всегда ли эти сокеты возвращают значение true при опросе по запросу из-за их потоковой природы?
//working snippet
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500000;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sid,&readfds);
//start server loop
for(;;){
//check if listening socket has any client requrests, timeout at 500 ms
int numsockets = select(sid+1,&readfds,NULL,NULL,&tv);
if(numsockets == -1){
if(errno == 4){
printf("SIGINT recieved in select\n");
FD_ZERO(&readfds);
myhandler(SIGINT);
}else{
perror("server select");
exit(1);
}
}
//check if listening socket is ready to be read after select returns
if(FD_ISSET(sid, &readfds)){
int newsocketfd = accept(sid, (struct sockaddr*)&client_addr, &addrsize);
if(newsocketfd == -1){
if(errno == 4){
printf("SIGINT recieved in accept\n");
myhandler(SIGINT);
}else{
perror("server accept");
exit(1);
}
}else{
s->forkThreadForClient(newsocketfd);
}
}
//non working snippet
//setup clients socket with select functionality
struct timeval ctv;
ctv.tv_sec = 0;
ctv.tv_usec = 500000;
fd_set creadfds;
FD_ZERO(&creadfds);
FD_SET(csid,&creadfds);
for(;;){
//check if listening socket has any client requrests, timeout at 500 ms
int numsockets = select(csid+1,&creadfds,NULL,NULL,&ctv);
if(numsockets == -1){
if(errno == 4){
printf("SIGINT recieved in client select\n");
FD_ZERO(&creadfds);
myhandler(SIGINT);
}else{
perror("server select");
exit(1);
}
}else{
printf("Select returned %i\n",numsockets);
}
if(FD_ISSET(csid,&creadfds)){
//read header
unsigned char header[11];
for(int i=0;i<11;i++){
if(recv(csid, rubyte, 1, 0) != 0){
printf("Received %X from client\n",*rubyte);
header[i] = *rubyte;
}
}
Любая помощь будет оценена.
Спасибо за ответы, но я не верю, что это имеет много общего со значением тайм-аута внутри цикла. Я проверил это, и даже если телевизор сбрасывается и fd_set обнуляется каждый раз, когда сервер зацикливается, select все равно возвращает 1 сразу. Я чувствую, что есть проблема с тем, как select обрабатывает мой TCP-сокет. Каждый раз, когда я устанавливаю, выбирает самый высокий идентификатор сокета, чтобы охватить мой TCP-сокет, он немедленно возвращается с этим набором сокетов. Также клиент ничего не отправляет, просто подключается.