Unix Programming - Using select

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > September 2006 > Using 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 Using select
mrunalp@gmail.com

2006-09-16, 1:43 pm

Hi,
I am making an application where there are a ring of processes each
connected to the left and right by TCP sockets to form a ring.
After forming the ring they send messages to each other. Each can send
either left or right.
I got the ring set up.
Now am using select to listen for messages as below

for(;;)
{
printf("\n1");
readfds = master;//reset the readfs from master which has all fds
if (select(fdmax+1, &read_set, NULL, NULL, NULL) == -1) {
perror("select");
exit(1);
}
printf("\n2");

for(i=0;i<=fdmax;i++)
{
if(FD_ISSET(i, &readfs))
{
if ((numbytes=recv(i, buffer,SIZE, 0)) <= 0)
{
//error check
}
else
{

data = (int *)(malloc(numbytes));
memcpy(
printf("\ndata:");
for(i=0;i<numbytes/sizeof(int);i++)
printf(" %d",data[i]);
memcpy(sendbuf,data,numbytes);
if(!fork()){
//sendall from beej guide to send all data
if (sendall(right_fd, sendbuf, &numbytes) == -1) {
perror("sendall");
printf("We only sent %d bytes", numbytes);
}
close(right_fd);
}

printf("\nDone sending..!!\n");
exit(0);
}//fork ends
}
..
So when data comes it is read and then sent to the right.
The problem is that each process in the ring is able to read only
once.After all of them hang.
My question is that is some call making them block?
I have verified they are hung after one receive and send because the
two printf statements before and after select do not print more than
once.
Thanks

Nils O. Selåsdal

2006-09-16, 1:43 pm

mrunalp@gmail.com wrote:
> Hi,
> I am making an application where there are a ring of processes each
> connected to the left and right by TCP sockets to form a ring.
> After forming the ring they send messages to each other. Each can send
> either left or right.
> I got the ring set up.
> Now am using select to listen for messages as below

Remeber that tcp carries a stream, not messages. Data
sent using one send call might be received with several recv calls
and vice versa.

[...]
> So when data comes it is read and then sent to the right.
> The problem is that each process in the ring is able to read only
> once.After all of them hang.
> My question is that is some call making them block?

Use strace or a similar tool to see which syscalls it performs,
thus you should see where it blocks.


> I have verified they are hung after one receive and send because the
> two printf statements before and after select do not print more than
> once.
> Thanks
>



--
Nils O. Selåsdal
www.utelsystems.com
Maxim Yegorushkin

2006-09-16, 1:43 pm

mrunalp@gmail.com wrote:

> I am making an application where there are a ring of processes each
> connected to the left and right by TCP sockets to form a ring.
> After forming the ring they send messages to each other. Each can send
> either left or right.


Apologies, if this is not relevant. If they receive and then send data
unmodified you could consider using udp multicast.

mrunalp@gmail.com

2006-09-16, 1:43 pm

>Remeber that tcp carries a stream, not messages. Data
>sent using one send call might be received with several recv calls
>and vice versa.


Hi,
However even if I don't make multiple calls to recv I should get some
bytes, right?So numbytes should contain some number of bytes greater
than zero Or will recv just block?
Thanks

mrunalp@gmail.com

2006-09-16, 1:43 pm


Maxim Yegorushkin wrote:
> mrunalp@gmail.com wrote:
>
>
> Apologies, if this is not relevant. If they receive and then send data
> unmodified you could consider using udp multicast.


Hi,
Thanks for the reply.But I have to modify the data later on. Right now
for testing I am just sending the same message as is.
Thanks

Nils O. Selåsdal

2006-09-16, 1:43 pm

mrunalp@gmail.com wrote:
>
> Hi,
> However even if I don't make multiple calls to recv I should get some
> bytes, right?So numbytes should contain some number of bytes greater
> than zero Or will recv just block?


When select indicates you can read, you normally can read
once, and it will fetch the data that's there.

In some circumstances , atleast with UDP the data
can be gone in the mean time and cause the read to block.

If you just run strace, you will see where it blocks (unless it's
stuck in a busy loop).
Spoon

2006-09-16, 1:43 pm

Nils O. Selåsdal wrote:

> When select indicates you can read, you normally can read
> once, and it will fetch the data that's there.
>
> In some circumstances, at least with UDP, the data
> can be gone in the mean time and cause the read to block.


Can you give an example how this can happen?
Where did the datagram go?
Nils O. Selåsdal

2006-09-16, 1:43 pm

Spoon wrote:
> Nils O. Selåsdal wrote:
>
>
> Can you give an example how this can happen?
> Where did the datagram go?

It might have been discarded because something else needed
memory more. Linux does/used to(?) indicate udp data available
before checking the checksum and later on discarding it if it was wrong.
David Schwartz

2006-09-16, 1:43 pm


mrunalp@gmail.com wrote:

> if(!fork()){
> //sendall from beej guide to send all data
> if (sendall(right_fd, sendbuf, &numbytes) == -1) {
> perror("sendall");
> printf("We only sent %d bytes", numbytes);
> } // X
> close(right_fd);
> } // Y


> printf("\nDone sending..!!\n");
> exit(0);
> }//fork ends (NO, IT DOESN'T)


I added the 'X', 'Y', and the 'NO, IT DOESN'T'. You miscounted your {'s
and }'s. The 'X' marks the close of the 'if(sendall' block, so the Y
marks the close of the 'fork' block.

Also, this causes the original process to do the sending and the new
process continue. I would suggest changing this to 'if(fork()==0){',
which tests if this is the child.

DS

David Schwartz

2006-09-16, 1:43 pm


Spoon wrote:

> Nils O. Sel=E5sdal wrote:


[vbcol=seagreen]
[vbcol=seagreen]
> Can you give an example how this can happen?


If the implementation decides to discard the datagram. This used to
permit a nasty denial of service attack against inetd on Linux.

Another possibility would be if in-between when you called 'select' and
when 'select' returned, you re-associated the same descriptor with a
different underlying socket. Linux keeps the 'select' associated with
the original underlying socket.

> Where did the datagram go?


UDP datagrams can be discarded. The only circumstance I know of in
which they can't be is after a recv(MSG_PEEK).

DS

mrunalp@gmail.com

2006-09-16, 1:43 pm

Hi,
I got it working by changing the for loop i.e. for(i=0;i<=fdmax;i++)
{
if(FD_ISSET(i, &readset))
...
}
to just checking FD_ISSET for the two ports I am interested in. It
works but still beats me why the for loop doesn't work. (I had
checked.. the braces were properly balanced)

Thanks

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com