Я пытаюсь использовать функцию выбора, чтобы иметь неблокирующий ввод / вывод между сервером и 1 клиентом (не более), где общение проходит хорошо (может отправлять в любое время, а другой получит, не ожидая отправки) , Я нашел учебник с некоторым кодом и попытался адаптировать его к своему. Это то, что у меня есть -
Сервер
#define PORT "4950"
#define STDIN 0
struct sockaddr name;
void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET)
return &(((struct sockaddr_in*)sa)->sin_addr);
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int agrc, char** argv) {
int status, sock, adrlen, new_sd;
struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results
//store the connecting address and size
struct sockaddr_storage their_addr;
socklen_t their_addr_size;
fd_set read_flags,write_flags; // the flag sets to be used
struct timeval waitd; // the max wait time for an event
int sel; // holds return value for select();
//socket infoS
memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address
//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
//make socket
sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sock < 0) {
printf("\nserver socket failure %m", errno);
exit(1);
}
//allow reuse of port
int yes=1;
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
//unlink and bind
unlink("127.0.0.1");
if(bind (sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nBind error %m", errno);
exit(1);
}
freeaddrinfo(servinfo);
//listen
if(listen(sock, 5) < 0) {
printf("\nListen error %m", errno);
exit(1);
}
their_addr_size = sizeof(their_addr);
//accept
new_sd = accept(sock, (struct sockaddr*)&their_addr, &their_addr_size);
if( new_sd < 0) {
printf("\nAccept error %m", errno);
exit(1);
}
set_nonblock(new_sd);
cout<<"\nSuccessful Connection!";
char* in = new char[255];
char* out = new char[255];
int numSent;
int numRead;
while(1) {
waitd.tv_sec = 10;
FD_ZERO(&read_flags);
FD_ZERO(&write_flags);
FD_SET(new_sd, &read_flags);
if(strlen(out) != 0)
FD_SET(new_sd, &write_flags);
sel = select(new_sd+1, &read_flags, &write_flags, (fd_set*)0, &waitd);
if(sel < 0)
continue;
//socket ready for reading
if(FD_ISSET(new_sd, &read_flags)) {
FD_CLR(new_sd, &read_flags);
memset(&in, 0, sizeof(in));
if(recv(new_sd, in, sizeof(in), 0) <= 0) {
close(new_sd);
break;
}
else
cout<<"\n"<<in;
} //end if ready for read
//socket ready for writing
if(FD_ISSET(new_sd, &write_flags)) {
FD_CLR(new_sd, &write_flags);
send(new_sd, out, strlen(out), 0);
memset(&out, 0, sizeof(out));
}
} //end while
cout<<"\n\nExiting normally\n";
return 0;
}
Клиент (в основном тот же, только за исключением вызова на прием) -
#define PORT "4950"
struct sockaddr name;
void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET)
return &(((struct sockaddr_in*)sa)->sin_addr);
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int agrc, char** argv) {
int status, sock, adrlen;
struct addrinfo hints;
struct addrinfo *servinfo; //will point to the results
fd_set read_flags,write_flags; // the flag sets to be used
struct timeval waitd; // the max wait time for an event
int sel; // holds return value for select();
memset(&hints, 0, sizeof hints); //make sure the struct is empty
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM; //tcp
hints.ai_flags = AI_PASSIVE; //use local-host address
//get server info, put into servinfo
if ((status = getaddrinfo("127.0.0.1", PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
//make socket
sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
if (sock < 0) {
printf("\nserver socket failure %m", errno);
exit(1);
}
if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) {
printf("\nclient connection failure %m", errno);
exit(1);
}
cout<<"\nSuccessful connection!";
set_nonblock(sock);
char* out = new char[255];
char* in = new char[255];
int numRead;
int numSent;
while(1) {
waitd.tv_sec = 10;
FD_ZERO(&read_flags);
FD_ZERO(&write_flags);
FD_SET(sock, &read_flags);
if(strlen(out) != 0)
FD_SET(sock, &write_flags);
sel = select(sock+1, &read_flags, &write_flags, (fd_set*)0, &waitd);
if(sel < 0)
continue;
//socket ready for reading
if(FD_ISSET(sock, &read_flags)) {
FD_CLR(sock, &read_flags);
memset(&in, 0, sizeof(in));
if(recv(sock, in, sizeof(in), 0) <= 0) {
close(sock);
break;
}
else
cout<<"\n"<<in;
} //end if ready for read
//socket ready for writing
if(FD_ISSET(sock, &write_flags)) {
FD_CLR(sock, &write_flags);
send(sock, out, strlen(out), 0);
memset(&out, 0, sizeof(out));
}
} //end while
cout<<"\n\nExiting normally\n";
return 0;
}
Проблема в том, что когда я запускаю их, ничего не происходит. Я могу напечатать в одном и нажать Enter, и ничего не появляется на другом экране (и наоборот). Это не вся информация для отладки, и это моя первая настоящая попытка использования select, поэтому я подумал, что, может быть, я просто не подозреваю о чем-то простом. Если что-то может быть замечено как неправильное или странное, пожалуйста, укажите на это, любая помощь приветствуется.