Unix Programming - help with select()

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > May 2005 > help with select()





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author help with select()
jessethepro

2005-05-21, 2:52 am

Hi all,

I have been racking my brain for days over the select() call. I use it

to monitor a socket and stdin. I run the program in two terminal
windows on localhost. The program is designed to allow two processes
to send and receive messages to each other. The problem is once one of

the processes sends its first message and the second process receives
it, the receiving processes is unable to send a message, but can
continue to receive. The code is the same for both processes I just
switch the the defined in and out ports. a copy of the program is
below and it compiles and runs on unix machines. The end result is a
p2p chat program I am designing. The program will run off of a
refferal system without a centralized server.

Thank you for any help
Jesse Johnson

//code
/*
** dsoc.c IM program
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/select.h>
#include <fcntl.h>
/* in order to run the program so the two processes can speak to each
other
** copy the program to a seperate file and switch the two ports below
*/
#define MYPORT_IN 20001 // the port users will be connecting to
#define MYPORT_OUT 20000 //port users will be writing to
#define MAXBUFLEN 100
int main(void){
int sockfd_in;
int sockfd_out;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int addr_len, numbytes;
char buf[MAXBUFLEN];
char string[100];
struct timeval tv;
int ready; //check if ready for input or output
fd_set read_fds;
fd_set write_fds;
tv.tv_sec = 0;
tv.tv_usec = 1000;
if ((sockfd_in = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket_in");
exit(1);
}
if ((sockfd_out = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket_out");
exit(1);
}
FD_ZERO(&read_fds);
FD_SET(sockfd_in, &read_fds);
FD_SET(STDIN_FILENO, &read_fds);
FD_SET(sockfd_out, &write_fds);
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT_IN); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(MYPORT_OUT); // short, network byte order
inet_aton("127.0.0.1", &(their_addr.sin_addr));
memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the
struct
if (bind(sockfd_in, (struct sockaddr *)&my_addr, sizeof(struct
sockaddr)) == -1){
perror("bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
for(;;){
//block until stdin or sockfd_in have input
ready = select(sockfd_in + 1, &read_fds, NULL, NULL, NULL);
printf("here\n");
if(ready > 0){
if(FD_ISSET(sockfd_in, &read_fds)){
printf("in\n");
if ((numbytes=recvfrom(sockfd_in, buf, MAXBUFLEN-1, 0, (struct
sockaddr *)&their_addr, &addr_len)) == -1){
perror("recvfrom");
exit(1);
}
printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
printf("packet is %d bytes long\n",numbytes);
buf[numbytes] = '\0';
printf("packet contains \"%s\"\n",buf);
//close(sockfd_in);
}
if(FD_ISSET(STDIN_FILENO, &read_fds)){
fgets(string, 100, stdin);
printf("out\n");
if ((numbytes=sendto(sockfd_out, string, strlen(string), 0, (struct
sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1){
perror("sendto");
exit(1);
}
printf("sent %d bytes to %s\n",
numbytes,inet_ntoa(their_addr.sin_addr));
//close(sockfd_out);
}
}
if(ready < 0){
perror("select");
}
}
return 0;
}

Fletcher Glenn

2005-05-21, 2:52 am

In your code below, you use read_fds in the select call. Do you understand
that read_fds is altered by the select call? You must restore read_fds back
to what you want to monitor before you reuse it in a select call.

--

Fletcher Glenn

"jessethepro" <jessethepro@mac.com> wrote in message
news:1116643659.587737.251090@g43g2000cwa.googlegroups.com...
> Hi all,
>
> I have been racking my brain for days over the select() call. I use it
>
> to monitor a socket and stdin. I run the program in two terminal
> windows on localhost. The program is designed to allow two processes
> to send and receive messages to each other. The problem is once one of
>
> the processes sends its first message and the second process receives
> it, the receiving processes is unable to send a message, but can
> continue to receive. The code is the same for both processes I just
> switch the the defined in and out ports. a copy of the program is
> below and it compiles and runs on unix machines. The end result is a
> p2p chat program I am designing. The program will run off of a
> refferal system without a centralized server.
>
> Thank you for any help
> Jesse Johnson
>
> //code
> /*
> ** dsoc.c IM program
> */
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <errno.h>
> #include <string.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <arpa/inet.h>
> #include <time.h>
> #include <sys/select.h>
> #include <fcntl.h>
> /* in order to run the program so the two processes can speak to each
> other
> ** copy the program to a seperate file and switch the two ports below
> */
> #define MYPORT_IN 20001 // the port users will be connecting to
> #define MYPORT_OUT 20000 //port users will be writing to
> #define MAXBUFLEN 100
> int main(void){
> int sockfd_in;
> int sockfd_out;
> struct sockaddr_in my_addr; // my address information
> struct sockaddr_in their_addr; // connector's address information
> int addr_len, numbytes;
> char buf[MAXBUFLEN];
> char string[100];
> struct timeval tv;
> int ready; //check if ready for input or output
> fd_set read_fds;
> fd_set write_fds;
> tv.tv_sec = 0;
> tv.tv_usec = 1000;
> if ((sockfd_in = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
> perror("socket_in");
> exit(1);
> }
> if ((sockfd_out = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
> perror("socket_out");
> exit(1);
> }
> FD_ZERO(&read_fds);
> FD_SET(sockfd_in, &read_fds);
> FD_SET(STDIN_FILENO, &read_fds);
> FD_SET(sockfd_out, &write_fds);
> my_addr.sin_family = AF_INET; // host byte order
> my_addr.sin_port = htons(MYPORT_IN); // short, network byte order
> my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
> memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
> their_addr.sin_family = AF_INET; // host byte order
> their_addr.sin_port = htons(MYPORT_OUT); // short, network byte order
> inet_aton("127.0.0.1", &(their_addr.sin_addr));
> memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the
> struct
> if (bind(sockfd_in, (struct sockaddr *)&my_addr, sizeof(struct
> sockaddr)) == -1){
> perror("bind");
> exit(1);
> }
> addr_len = sizeof(struct sockaddr);
> for(;;){
> //block until stdin or sockfd_in have input
> ready = select(sockfd_in + 1, &read_fds, NULL, NULL, NULL);
> printf("here\n");
> if(ready > 0){
> if(FD_ISSET(sockfd_in, &read_fds)){
> printf("in\n");
> if ((numbytes=recvfrom(sockfd_in, buf, MAXBUFLEN-1, 0, (struct
> sockaddr *)&their_addr, &addr_len)) == -1){
> perror("recvfrom");
> exit(1);
> }
> printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr));
> printf("packet is %d bytes long\n",numbytes);
> buf[numbytes] = '\0';
> printf("packet contains \"%s\"\n",buf);
> //close(sockfd_in);
> }
> if(FD_ISSET(STDIN_FILENO, &read_fds)){
> fgets(string, 100, stdin);
> printf("out\n");
> if ((numbytes=sendto(sockfd_out, string, strlen(string), 0, (struct
> sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1){
> perror("sendto");
> exit(1);
> }
> printf("sent %d bytes to %s\n",
> numbytes,inet_ntoa(their_addr.sin_addr));
> //close(sockfd_out);
> }
> }
> if(ready < 0){
> perror("select");
> }
> }
> return 0;
> }
>



jessethepro

2005-05-21, 5:49 pm

That would probably be the simple thing I couldn't figure out I do
I need to fully FD_ZERO and redo FD_SET on the file descriptors, or can
I just use FD_CLR on the descriptor that created the event and the
FD_SET it.


Jesse Johnson
I love using C commands as verbs.

Alex Fraser

2005-05-21, 5:49 pm

"jessethepro" <jessethepro@mac.com> wrote in message
news:1116688943.463967.115010@g43g2000cwa.googlegroups.com...
> That would probably be the simple thing I couldn't figure out I do
> I need to fully FD_ZERO and redo FD_SET on the file descriptors, or can
> I just use FD_CLR on the descriptor that created the event and the
> FD_SET it.


You can do anything you like that makes the fd_sets have the desired
descriptors set. There are two practical alternatives I know of: FD_ZERO,
followed by FD_SET for each descriptor, or a "master" fd_set which you copy
just before the select() call.

Alex


jessethepro

2005-05-21, 5:49 pm

I have seen using a master before and will try that

thank you
Jesse Johnson

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com