原问题
I am trying to use the select function to have non-blocking i/o between a server and 1 client (no more)
where the communication flows nicely (can send at any time and the other will receive without waiting to send).
I found a tutorial with some code and tried to adapt it to mine. This is what I have -
Server
#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 ", gai_strerror(status)); exit(1); } //make socket sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); if (sock < 0) { printf(" server 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(" Bind error %m", errno); exit(1); } freeaddrinfo(servinfo); //listen if(listen(sock, 5) < 0) { printf(" Listen 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(" Accept error %m", errno); exit(1); } set_nonblock(new_sd); cout<<" Successful 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<<" "<<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<<" Exiting normally "; return 0; }
Client
#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 ", gai_strerror(status)); exit(1); } //make socket sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); if (sock < 0) { printf(" server socket failure %m", errno); exit(1); } if(connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) < 0) { printf(" client connection failure %m", errno); exit(1); } cout<<" Successful 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<<" "<<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<<" Exiting normally "; return 0; }
The problem is that when I run them, nothing happens. I can type into one and hit enter and nothing shows up on the other screen (and vice versa).
Thats not a whole of information for me to debug and this is my first real attempt at using select so I thought maybe I am just unaware of something simple.
If anything can be spotted as wrong or weird please point it out, any help is appreciated.
Sterling 自问自答 https://stackoverflow.com/questions/6715736/using-select-for-non-blocking-sockets
#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 = {10, 0}; // 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 ", gai_strerror(status)); exit(1); } //make socket sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol); if (sock < 0) { printf(" server 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(" Bind error %m", errno); exit(1); } freeaddrinfo(servinfo); //listen if(listen(sock, 5) < 0) { printf(" Listen 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(" Accept error %m", errno); exit(1); } //set non blocking set_nonblock(new_sd); cout<<" Successful Connection! "; char in[255]; char out[255]; memset(&in, 0, 255); memset(&out, 0, 255); int numSent; int numRead; while(1) { FD_ZERO(&read_flags); FD_ZERO(&write_flags); FD_SET(new_sd, &read_flags); FD_SET(new_sd, &write_flags); FD_SET(STDIN_FILENO, &read_flags); FD_SET(STDIN_FILENO, &write_flags); sel = select(new_sd+1, &read_flags, &write_flags, (fd_set*)0, &waitd); //if an error with select if(sel < 0) continue; //socket ready for reading if(FD_ISSET(new_sd, &read_flags)) { //clear set FD_CLR(new_sd, &read_flags); memset(&in, 0, 255); numRead = recv(new_sd, in, 255, 0); if(numRead <= 0) { printf(" Closing socket"); close(new_sd); break; } else if(in[0] != '