This is a discussion on Help with Select within the Linux Networking forums, part of the Linux Forums category; Hi, I am trying to use the select() socket programming command to select between stdin and a connection. Currently, I ...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
Hi,
I am trying to use the select() socket programming command to select between stdin and a connection. Currently, I have a listening stream and stdin that I insert into the fd_set. The problem is that when I recognize FD_ISSET from stdin, I am stuck there. The loop does not return me to select() between stdin and listening socket. Similarly, when I accept a client, the loop does not return me to select between stdin and listeing socket. I don't know what to do. I want to be able to select continuously between stdin and the listening port after I have either accepted from a port or from stdin. I have pasted the codes that I am using for the listening to port and stdin and the code for the client. Please help. Thank you, Marcia Hon #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define max(a, b) ((a) > (b) ? a: b) int flushToEndOfLine(); int main(int argc, char *argv[]) { fd_set master; struct sockaddr_in myaddr; struct sockaddr_in remoteaddr; int fdmax; int listenerSocket; int newfd; char buf[256]; int yes = 1; int addrlen; int i, j; if(argc != 2) { fprintf(stderr, "Usage: %s <listen_port>\n", argv[0]); exit(1); } FD_ZERO(&master); //clear master set // get listenerSocket if((listenerSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } // lose socket already in use error message if(setsockopt(listenerSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } // bind myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_port = htons(atoi(argv[1])); memset(&(myaddr.sin_zero), '\0', 8); if(bind(listenerSocket, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { perror("bind"); exit(1); } // listen if(listen(listenerSocket, 5) == -1) { perror("listen"); exit(1); } FD_SET(listenerSocket, &master); FD_SET(0, &master); fdmax = max(listenerSocket, 0); while(1){ printf("select\n"); if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){ perror("select"); exit(1); } if(FD_ISSET(listenerSocket, &master)){ addrlen = sizeof(remoteaddr); if((newfd = accept(listenerSocket, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) { perror("accept"); } printf("new connection from client\n"); close(newfd); } else { if(FD_ISSET(0, &master)) { printf("user entered data \n"); flushToEndOfLine(); } } } return 0; } int flushToEndOfLine() { int c; while ( (c=getchar()) != EOF && c != '\n' ); return; } client: //WHAT IF SHORT IS NOT 2 BYTES?!?!?!? #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #define FILE_TBYTES 4 //bytes at the beginning of file that specify how many bytes are in this block being sent #define MAX_BYTES 1000 //breaks up file into this many bytes and sends this many bytes at a time #define MAX_BSEND_RETRY 3 //how many times to retry sending a block of MAX_BYTES before fail #define DEBUG //prototypes int establish_connection (const char * name, unsigned short port); int send_stream (int sockfd, const char * data, int len); unsigned long getFileSize(char *fileName); //check ip or dns int main(int argc, char *argv[]) { FILE *fp; int j; //loop counters short int i; //this better be 2 bytes char * buffer; unsigned long *tmp; unsigned short port; int sockfd; unsigned long fileSize; if ((buffer = (char *) malloc (MAX_BYTES)) == NULL) { fprintf(stderr, "Not enough memory for a file input buffer of %d\n", MAX_BYTES); exit(1); } //Check if 3 arguments passed if (argc !=4) { fprintf(stderr, "Usage: %s <ip> <port> <file>\n", argv[0]); exit(1); } //no check! port = atoi(argv[2]); #ifdef DEFINE printf("Arguments Passed:\n"); printf("IP: %s\n", argv[1]); printf("PORT: %d\n", port); printf("FILE: %s\n", argv[3]); printf("\n"); #endif //open file if ((fp = fopen(argv[3],"r")) == NULL) { fprintf(stderr, "Error: Could not open %s\n", argv[3]); exit(1); } if ((sockfd = establish_connection (argv[1], port)) == -1) { fprintf(stderr, "Error establishing connection\n"); fclose(fp); exit(1); } //buffer = "Hello World"; //send_stream(sockfd, buffer, 11); //send file size fileSize = getFileSize(argv[3]); tmp = (unsigned long *) &buffer[0]; *tmp = (unsigned long) htonl(fileSize); send_stream(sockfd, buffer, 4); printf("File Size: %d\n", fileSize); while (!feof(fp)) { //read some bytes for (i = 0; i<MAX_BYTES; i++) { buffer[i] = fgetc(fp); if (feof(fp)) //end of file true break; } //echo bytes to screen for (j=0; j<i; j++) { //put send function here //printf("%c", buffer[j]); } if (!send_stream(sockfd, buffer, i)) { fprintf(stderr, "Error sending a block\n"); exit(1); } } //close file fclose(fp); close(sockfd); return 0; //exited succesfully } //pass name of the host and port number only! //-1 fail, sockfd success int establish_connection (const char * name, unsigned short port) { struct sockaddr_in their_addr; int sockfd; int r; //returned from functions struct hostent * h; sockfd = socket(AF_INET, SOCK_STREAM, 0); //set up the structure their_addr.sin_family = AF_INET; their_addr.sin_port = htons(port); // short, network byte order memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct h=gethostbyname(name); if (h == NULL) return -1; //1. make *h_addr_list[0] be a in_addr * //2. dereference this pointer and assign it to their_addr.sin_addr their_addr.sin_addr = *((struct in_addr *)h->h_addr); printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr))); printf("IP Address : %s\n", inet_ntoa(their_addr.sin_addr)); printf("Port: %d \n", ntohs(their_addr.sin_port)); if((connect(sockfd, (struct sockaddr *) &their_addr, sizeof(struct sockaddr))) == -1) return -1; return sockfd; } //sends data //connect may return that it sent less, this function sends the rest //return 0 on fail, 1 on success int send_stream (int sockfd, const char * data, int len) { int bytes_sent, newlen; const void * newdata; bytes_sent = send(sockfd, data, len,0); if (bytes_sent < 0) return 0; while (bytes_sent < len - 1) { //if we sent 10 bytes, we sent bytes 0...9 //need to send byte 10... newdata = &data[bytes_sent]; bytes_sent = send(sockfd, newdata, len - bytes_sent, 0); if (bytes_sent < 0) return 0; } return 1; } unsigned long getFileSize(char *fileName) { unsigned long fileSize; FILE *f=fopen(fileName, "rb"); if(f==NULL) { fprintf(stderr, "Cannot open file.\n"); exit(EXIT_FAILURE); } else { if(fseek(f, 0, SEEK_END)!=0) { fprintf(stderr, "Cannot use file.\n"); exit(EXIT_FAILURE); } fileSize=ftell(f); } if(fclose(f)!=0) { fprintf(stderr, "Cannot close file.\n"); exit(EXIT_FAILURE); } return fileSize; } |
|
|||
|
On Sat, 14 Feb 2004 15:42:52 GMT, "Marcia Hon" <honm@rogers.com>
wrote: This has nothing to do with ANSI C, so I've removed it from the Followup-To field. (I should probably have removed comp.os.linux.networking, too.) >while(1){ > >printf("select\n"); > >if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){ > >perror("select"); > >exit(1); > >} select() will destroy the "master" parameter each time you call it. So your code should look like this: saved_master = master; while(1){ printf("select\n"); master = saved_master; if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){ perror("select"); exit(1); } BTW, your code is ugly indented. If the bug in your code hadn't been easy to spot, probably none would have taken the time to have a look at it. -- Fernando Gont e-mail: fernando@ANTISPAM.gont.com.ar [To send a personal reply, please remove the ANTISPAM tag] |
|
|||
|
"Marcia Hon" <honm@rogers.com> writes:
> I am trying to use the select() socket programming command to select between > stdin and a connection. Currently, I have a listening stream and stdin that > I insert into the fd_set. The problem is that when I recognize FD_ISSET from > stdin, I am stuck there. The loop does not return me to select() between > stdin and listening socket. Similarly, when I accept a client, the loop does > not return me to select between stdin and listeing socket. I don't know what > to do. I want to be able to select continuously between stdin and the > listening port after I have either accepted from a port or from stdin. Select modifies its arguments. You need to put the FD_SET invocations *inside* the loop, or save a copy of 'master' somewhere. -- James Carlson, IP Systems Group <james.d.carlson@sun.com> Sun Microsystems / 1 Network Drive 71.234W Vox +1 781 442 2084 MS UBUR02-212 / Burlington MA 01803-2757 42.497N Fax +1 781 442 1677 |