use of select()

J

jessethepro

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;
}
 
A

Alex Fraser

jessethepro said:
I have been racking my brain for days over the select() call. I use it
to monitor a socket and stdin.
[snip]

The select() function and sockets are not part of standard C and are
therefore off-topic here. Perhaps would be an
appropriate newsgroup.

<OT>
From a glance at your code, it looks like you are making the common mistake
of not setting up the fd_sets before each call to select(), which is
necessary because they are modified by the call.
</OT>

Alex
 
K

Keith Thompson

jessethepro said:
I have been racking my brain for days over the select() call.
[snip]

The select() function is not standard C. Try comp.unix.programmer.
 
S

SM Ryan

# //block until stdin or sockfd_in have input

# if(FD_ISSET(STDIN_FILENO, &read_fds)){
# fgets(string, 100, stdin);

fgets doesn't return until it gets a line or end of file. Having some
input available doesn't mean it has enough for fgets to return.

If you're reading and writing to the same process with blocking I/O,
there's a deadlock hazard if both processes block waiting for output
from the other.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top