PDA

View Full Version : selct()



India
02-02-2011, 03:32 AM
Hi,
What's worng here. My select() call always return 0. Here my parent is the server and child is the client. My select() call is in the server process.


while (1) {
printf("----------Inside select()\n");
sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
FD_SET(sockfd, &read_fd);
if (sel > 0) {
if (FD_ISSET(sockfd, &read_fd)) {
clilen = sizeof(clientAdd);
if ( (newsockfd = accept(sockfd, (struct sockaddr *)&clientAdd, &clilen) < 0)){
printf("ERROR SERVER: Accept() failed\n");
exit(1);
}
//make child process
printf("forking now\n");
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child process

printf("this is the child\n");
// The sockfd has data to be read
close(sockfd);
n = read(newsockfd, buffer, 255);
printf("received size: %d\n", n);
printf("%s\n", buffer);
close(newsockfd);
} else { //parent process
printf("This is the parents\n");
close(newsockfd);
}
} else {
printf("FD_ISSET() did not set\n");
}
}else if (sel < 0) {
/* An error ocurred, just print it to stdout */
perror("select");
} else if (sel == 0) {
printf("select is returnig 0\n\n");
break;
}
}

Salem
02-02-2011, 03:53 AM
> sel = select(sockfd, &read_fd, NULL, NULL, &timeout);


nfds is the highest-numbered file descriptor in any of the three sets,
plus 1.

If sockfd is the only thing set in read_fd, then it will always return 0.

Try sockfd+1

India
02-02-2011, 08:09 AM
Thank U for the reply.................. But I have tried sockfd+1 as U have said. It always returning 0

Salem
02-02-2011, 08:16 AM
> FD_SET(sockfd, &read_fd);
Why is this AFTER your select call?
I think your set is actually empty.

How did you set up timeout?
If you're on Linux, then note this from the manual page
"On Linux, select() modifies timeout to reflect the amount of time not slept;"

Did you FD_ZERO your set before you started?

Post some of the code leading up to your select call - context is important.

India
02-02-2011, 11:15 PM
Thank again for U R reply. Here is the code before while(1)


fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
FD_ZERO(&read_fd);

pid_t pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);

printf("----------serverProcess Running-------\n");

if (sockfd < 0) {
printf("serverProcess ERROR: Opening Socket\n");
exit(0);
}
bzero((char *) &serverAdd, sizeof(serverAdd));
serverAdd.sin_family = AF_INET;
serverAdd.sin_addr.s_addr = INADDR_ANY;
serverAdd.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serverAdd,sizeof(serverAdd)) < 0) {
printf("serverProcess ERROR: on Binding\n");
pid = getpid();
kill(pid1, SIGKILL); // Kill my child(client) process
exit(0);
}
listen(sockfd,1);

Salem
02-03-2011, 03:13 AM
Firstly, it is "your", not "U R" (http://www.catb.org/~esr/faqs/smart-questions.html#writewell)

So I see I was right then, you don't correctly initialise your set.

Do this


while ( 1 ) {
fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
FD_ZERO(&read_fd);
FD_SET(sockfd, &read_fd);
sel = select(sockfd+1, &read_fd, NULL, NULL, &timeout);

India
02-04-2011, 12:51 AM
Thank You for your Reply. But still its returning ZERO. I debugged using gdb. The sel value is more than ZERO.


131 FD_SET(sockfd, &read_fd);
(gdb)
133 printf("----------Inside select()\n");
(gdb)
----------Inside select()
134 sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
(gdb) print sel
$1 = 5861952
(gdb)
$2 = 5861952
(gdb) n
135 if (sel > 0) {
(gdb)
165 }else if (sel < 0) {
(gdb) print sel
$3 = 0

You can check here. At line number 134 the sel value is 5861952 which is greater than ZERO. So it should go to line number 136 onwards. But its not going there.
I tried declaring sel as unsigned int since its value is too large. But still its returning ZERO.

Salem
02-04-2011, 01:59 AM
> At line number 134 the sel value is 5861952 which is greater than ZERO
At line 134, sel is garbage because you haven't called select() yet to get a return value assigned.

Try say
int sel = 11223344;
....
sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
and then step through with gdb.

If you've only got 1 descriptor set in your fd sets, then the only possible values select can return are
-1 => error
0 => no fd's ready
1 => the fd you set is ready.

The print at line 165 is the assigned value, which is zero.

And you're still not doing +1 on the first parameter to select.

Post your latest code.
I see you moved the FD_SET(), I'm wondering what else you have done.

India
02-08-2011, 01:01 AM
Here is my complete code.............. Please do help


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define portno 3386

void clientProcess(char *argv[]) {
extern LABEL;
int sockfd,n;
struct sockaddr_in serverAdd;
struct hostent *server;
char buffer[256];
// Create Socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("clientProcess ERROR: Socket Not Created");
}
server = gethostbyname("127.0.0.1");//argv[1]);
if (server == NULL) {
printf(" No such HOST\n");
exit(0);
}
bzero((char *) &serverAdd, sizeof(serverAdd));
serverAdd.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serverAdd.sin_addr.s_addr,server->h_length);
serverAdd.sin_port = htons(portno);

if (connect(sockfd,(const struct sockaddr *)&serverAdd,sizeof(serverAdd)) < 0) {
printf("clientProcess ERROR : NO Connect\n");
exit(0);
}
printf("-----------Inside clientProcess-------------\n\n");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0) {
printf("clientProcess ERROR: Writing \n");
}
bzero(buffer,256);
close(sockfd);
}

void serverProcess(char *argv[], int pid1) {

int sockfd, newsockfd, clilen, n;
int sel, i;
char buffer[256];
struct sockaddr_in serverAdd, clientAdd;

fd_set active_fd, read_fd; // two fd's
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;

FD_ZERO(&active_fd); // set zero for active_fd
FD_SET(sockfd, &active_fd);

pid_t pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);

printf("----------serverProcess Running-------\n");

if (sockfd < 0) {
printf("serverProcess ERROR: Opening Socket\n");
exit(0);
}
bzero((char *) &serverAdd, sizeof(serverAdd));
serverAdd.sin_family = AF_INET;
serverAdd.sin_addr.s_addr = INADDR_ANY;
serverAdd.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serverAdd,sizeof(serverAdd)) < 0) {
printf("serverProcess ERROR: on Binding\n");
pid = getpid();
kill(pid1, SIGKILL);
exit(0);
}
listen(sockfd,1);
while (1) {
read_fd = active_fd;
sel = select(sockfd+1, &read_fd, NULL, NULL, &timeout);
if(sel < 0) {
printf("select ERROR\n");
}
for(i = 0; i< (sockfd+1); i++) {
if (FD_ISSET(i, &read_fd)) {
if(i == sockfd) {
clilen = sizeof(clientAdd);
if ( (newsockfd = accept(sockfd, (struct sockaddr *)&clientAdd, &clilen) < 0)){
printf("ERROR SERVER: Accept() failed\n");
exit(1);
}
} else {
//make child process
printf("forking now\n");
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child process
printf("this is the child\n");
// The sockfd has data to be read
close(sockfd);
n = read(newsockfd, buffer, 255);
printf("received size: %d\n", n);
printf("%s\n", buffer);
close(newsockfd);
} else { //parent process
printf("This is the parents\n");
close(newsockfd);
}
}
}
}
}
close(newsockfd);// Close accepct descriptor
close(sockfd); // Close socket descriptor
}

int main(int argc, char *argv[]) {
int pid1, pid2;
if(argc < 1) {
printf("USEAGE: ./socket <portno> <localhost>\n");
exit(0);
}
pid1 = fork();
if(pid1 > 0) {
serverProcess(argv, pid1);
} else {
sleep(3);
clientProcess(argv);
}
return (0);
}

Salem
02-08-2011, 02:43 AM
Maybe compile with some warnings.


$ gcc -Wall bar.c
bar.c: In function ‘clientProcess’:
bar.c:12: warning: type defaults to ‘int’ in declaration of ‘LABEL’
bar.c:40: warning: implicit declaration of function ‘write’
bar.c:45: warning: implicit declaration of function ‘close’
bar.c:12: warning: unused variable ‘LABEL’
bar.c: In function ‘serverProcess’:
bar.c:78: warning: implicit declaration of function ‘getpid’
bar.c:93: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
/usr/include/sys/socket.h:214: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
bar.c:100: warning: implicit declaration of function ‘fork’
bar.c:109: warning: implicit declaration of function ‘read’
bar.c: In function ‘main’:
bar.c:135: warning: implicit declaration of function ‘sleep’
bar.c:126: warning: unused variable ‘pid2’
bar.c: In function ‘serverProcess’:
bar.c:61: warning: ‘sockfd’ is used uninitialized in this function


Do you see what is wrong here?


FD_ZERO(&active_fd); // set zero for active_fd
FD_SET(sockfd, &active_fd);

pid_t pid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);

I said this a week ago, it's getting old.


Also, check your indent style. It might look indented, but it isn't reflecting the program flow you intend.


if (i == sockfd) {
clilen = sizeof(clientAdd);
if ((newsockfd =
accept(sockfd, (struct sockaddr *) &clientAdd,
&clilen) < 0)) {
printf("ERROR SERVER: Accept() failed\n");
exit(1);
}
} else {
//make child process
printf("forking now\n");
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child process
printf("this is the child\n");
// The sockfd has data to be read
close(sockfd);
n = read(newsockfd, buffer, 255);
printf("received size: %d\n", n);
printf("%s\n", buffer);
close(newsockfd);
} else { //parent process
printf("This is the parents\n");
close(newsockfd);
}
}

Surely you mean to create a new process on the accept right?

Perhaps you need to use a function, so you can keep a better track of the scope of things.
Like


if (i == sockfd) {
spawnReaderThread();
}