Unix Programming - select and sockets problem

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > March 2005 > select and sockets problem





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 select and sockets problem
Ulrich Hobelmann

2005-03-27, 8:47 pm

Hi, I'm writing the most minimally useful sockets example, a
server and and a client.
The server accept one connection, services it like the client,
until the socket is closed.

Both client and server work by select()ing on 0 (stdin) and s (the
connection socket). They then read stuff from the active stream
into a buffer and out to stdout or the socket respectively.
So in effect this is a simple chat tool, with the server having
its own console too.

For some reason though the data doesn't get sent or isn't received
correctly. Both client and server are stuck in select() until I
type something in and hit enter. Now this data is read() and
write()en out to the socket. On the other side, however, select
doesn't wake up. Both sides are symmetric in this.

Here's code from the client:

static void connect(const char * server, int port)
{
int n;
fd_set streams;
// this connects and returns the fd
int s = newSocket(server, port);
FD_ZERO(&streams);
for (;;) {
FD_SET(0, &streams);
FD_SET(s, &streams);
n = select(2, &streams, 0, 0, 0);
if (n == -1) error("select: %s", strerror(errno));
// if stdin is set xfer from stdin to s
if (FD_ISSET(0, &streams) && xfer(0, s)) {
// if EOF in stdin
close(s);
return;
}
// if s is set xfer from s to stdout
if (FD_ISSET(s, &streams) && xfer(s, 1)) {
// if EOF in s
close(s);
return;
}
}
}

/* returns: EOF? */
static int xfer(int in, int out)
{
int n; char buf[128];
n = read(in, buf, 128);
if (n == -1) error("read: %s", strerror(errno));
if (n == 0) return 1;
write(out, buf, n);
return 0;
}

Am I doing anything wrong with the fd_sets?

Here's the server's main function:

static void listen(int port)
{
int n, s;
fd_set streams;
// creates listening socket
int sock = newServerSocket(port);
for (;;) {
// accepts and returns connection
s = serverSocketAccept(sock);
FD_ZERO(&streams);
for (;;) {
FD_SET(0, &streams);
FD_SET(s, &streams);
n = select(2, &streams, 0, 0, 0);
if (n == -1) error("select: %s", strerror(errno));
if (FD_ISSET(0, &streams) && xfer(0, s)) {
close(s);
close(sock);
return;
}
if (FD_ISSET(s, &streams) && xfer(s, 1)) {
close(s);
break;
}
}
}
}
Malte Starostik

2005-03-27, 8:47 pm

Ulrich Hobelmann schrieb:
> Hi, I'm writing the most minimally useful sockets example, a server and
> and a client.
> The server accept one connection, services it like the client, until the
> socket is closed.
>
> For some reason though the data doesn't get sent or isn't received
> correctly. Both client and server are stuck in select() until I type
> something in and hit enter. Now this data is read() and write()en out
> to the socket. On the other side, however, select doesn't wake up.
> Both sides are symmetric in this.
>
> FD_SET(0, &streams);
> FD_SET(s, &streams);
> n = select(2, &streams, 0, 0, 0);


The second argument to select() is often called nfds, which is a bit of
a misnomer as it might look like you need to pass the number of
filedescriptors. In fact, what you need to pass there is the maximum fd
included in any of the sets + 1, in your simple case s + 1.

HTH,
Malte
Malte Starostik

2005-03-27, 8:47 pm

Malte Starostik schrieb:
> The second argument to select() is often called nfds

^^^^^^ make that first *sigh*

Cheers,
Malte
Ulrich Hobelmann

2005-03-27, 8:47 pm

Malte Starostik wrote:
>
>
> The second argument to select() is often called nfds, which is a bit of
> a misnomer as it might look like you need to pass the number of
> filedescriptors. In fact, what you need to pass there is the maximum fd
> included in any of the sets + 1, in your simple case s + 1.


Thanks for the instant response! This has to be the classic
select() error. My manpage says: "The first nfds descriptors are
checked in each set; i.e., the descriptors from 0 through nfds-1
in the descriptor sets are examined."

I only read "the first nfds descriptors are checked" and thought
that refers to MY two descriptors

I guess select is very wasteful when I give it fd 0 and fd 200 :D

I even remember having made the same mistake a couple years back
(actually finding it on my own), but I don't seem to have the code
around.

(It works now)
moi

2005-03-28, 7:56 am

Ulrich Hobelmann wrote:
>


>
> I guess select is very wasteful when I give it fd 0 and fd 200 :D
>


Don't worry. You would notice.

> I even remember having made the same mistake a couple years back
> (actually finding it on my own), but I don't seem to have the code around.
>
> (It works now)


Good.
Just one detail: one of your static functions is called connect();
That will (at least) confuse human readers.

AvK
Ulrich Hobelmann

2005-03-29, 2:49 am

moi wrote:
> Good.
> Just one detail: one of your static functions is called connect();
> That will (at least) confuse human readers.


I know. A put all socket stuff behind abstractions, because the
socket API is really ugly IMHO

The static function is called connect (like the program), because
I couldn't find a better name for it.
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com