mirror of https://github.com/mkerrisk/man-pages
Relocated example program and made its .SH title "EXAMPLE".
This commit is contained in:
parent
0784f93ce4
commit
3618596929
|
@ -342,7 +342,162 @@ A simple example of the use of
|
||||||
can be found in the
|
can be found in the
|
||||||
.BR select (2)
|
.BR select (2)
|
||||||
manual page.
|
manual page.
|
||||||
.SH PORT FORWARDING EXAMPLE
|
.SS Select Law
|
||||||
|
Many people who try to use
|
||||||
|
.BR select ()
|
||||||
|
come across behavior that is
|
||||||
|
difficult to understand and produces non-portable or borderline
|
||||||
|
results.
|
||||||
|
For instance, the above program is carefully written not to
|
||||||
|
block at any point, even though it does not set its file descriptors to
|
||||||
|
non-blocking mode at all (see
|
||||||
|
.BR ioctl (2)).
|
||||||
|
It is easy to introduce
|
||||||
|
subtle errors that will remove the advantage of using
|
||||||
|
.BR select (),
|
||||||
|
hence I will present a list of essentials to watch for when using the
|
||||||
|
.BR select ()
|
||||||
|
call.
|
||||||
|
.TP
|
||||||
|
\fB1.\fP
|
||||||
|
You should always try to use
|
||||||
|
.BR select ()
|
||||||
|
without a timeout.
|
||||||
|
Your program
|
||||||
|
should have nothing to do if there is no data available.
|
||||||
|
Code that
|
||||||
|
depends on timeouts is not usually portable and is difficult to debug.
|
||||||
|
.TP
|
||||||
|
\fB2.\fP
|
||||||
|
The value \fInfds\fP must be properly calculated for efficiency as
|
||||||
|
explained above.
|
||||||
|
.TP
|
||||||
|
\fB3.\fP
|
||||||
|
No file descriptor must be added to any set if you do not intend
|
||||||
|
to check its result after the
|
||||||
|
.BR select ()
|
||||||
|
call, and respond
|
||||||
|
appropriately.
|
||||||
|
See next rule.
|
||||||
|
.TP
|
||||||
|
\fB4.\fP
|
||||||
|
After
|
||||||
|
.BR select ()
|
||||||
|
returns, all file descriptors in all sets
|
||||||
|
should be checked to see if they are ready.
|
||||||
|
.\" mtk, May 2006: the following isn't really true.
|
||||||
|
.\" Any file descriptor that is available
|
||||||
|
.\" for writing \fImust\fP be written to, and any file descriptor
|
||||||
|
.\" available for reading \fImust\fP be read, etc.
|
||||||
|
.TP
|
||||||
|
\fB5.\fP
|
||||||
|
The functions
|
||||||
|
.BR read (2),
|
||||||
|
.BR recv (2),
|
||||||
|
.BR write (2),
|
||||||
|
and
|
||||||
|
.BR send (2)
|
||||||
|
do \fInot\fP necessarily read/write the full amount of data
|
||||||
|
that you have requested.
|
||||||
|
If they do read/write the full amount, its
|
||||||
|
because you have a low traffic load and a fast stream.
|
||||||
|
This is not
|
||||||
|
always going to be the case.
|
||||||
|
You should cope with the case of your
|
||||||
|
functions only managing to send or receive a single byte.
|
||||||
|
.TP
|
||||||
|
\fB6.\fP
|
||||||
|
Never read/write only in single bytes at a time unless your are really
|
||||||
|
sure that you have a small amount of data to process.
|
||||||
|
It is extremely
|
||||||
|
inefficient not to read/write as much data as you can buffer each time.
|
||||||
|
The buffers in the example above are 1024 bytes although they could
|
||||||
|
easily be made larger.
|
||||||
|
.TP
|
||||||
|
\fB7.\fP
|
||||||
|
The functions
|
||||||
|
.BR read (2),
|
||||||
|
.BR recv (2),
|
||||||
|
.BR write (2),
|
||||||
|
and
|
||||||
|
.BR send (2)
|
||||||
|
as well as the
|
||||||
|
.BR select ()
|
||||||
|
call can return \-1 with
|
||||||
|
.I errno
|
||||||
|
set to \fBEINTR\fP,
|
||||||
|
or with
|
||||||
|
.I errno
|
||||||
|
set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP).
|
||||||
|
These results must be properly managed (not done properly
|
||||||
|
above).
|
||||||
|
If your program is not going to receive any signals then
|
||||||
|
it is unlikely you will get \fBEINTR\fP.
|
||||||
|
If your program does not
|
||||||
|
set non-blocking I/O, you will not get \fBEAGAIN\fP.
|
||||||
|
Nonetheless
|
||||||
|
you should still cope with these errors for completeness.
|
||||||
|
.TP
|
||||||
|
\fB8.\fP
|
||||||
|
Never call
|
||||||
|
.BR read (2),
|
||||||
|
.BR recv (2),
|
||||||
|
.BR write (2),
|
||||||
|
or
|
||||||
|
.BR send (2)
|
||||||
|
with a buffer length of zero.
|
||||||
|
.TP
|
||||||
|
\fB9.\fP
|
||||||
|
If the functions
|
||||||
|
.BR read (2),
|
||||||
|
.BR recv (2),
|
||||||
|
.BR write (2),
|
||||||
|
and
|
||||||
|
.BR send (2)
|
||||||
|
fail
|
||||||
|
with errors other than those listed in \fB7.\fP,
|
||||||
|
or one of the input functions returns 0, indicating end of file,
|
||||||
|
then you should \fInot\fP pass that descriptor to
|
||||||
|
.BR select ()
|
||||||
|
again.
|
||||||
|
In the above example,
|
||||||
|
I close the descriptor immediately, and then set it to \-1
|
||||||
|
to prevent it being included in a set.
|
||||||
|
.TP
|
||||||
|
\fB10.\fP
|
||||||
|
The timeout value must be initialized with each new call to
|
||||||
|
.BR select (),
|
||||||
|
since some operating systems modify the structure.
|
||||||
|
.BR pselect ()
|
||||||
|
however does not modify its timeout structure.
|
||||||
|
.TP
|
||||||
|
\fB11.\fP
|
||||||
|
I have heard that the Windows socket layer does not cope with OOB data
|
||||||
|
properly.
|
||||||
|
It also does not cope with
|
||||||
|
.BR select ()
|
||||||
|
calls when no file
|
||||||
|
descriptors are set at all.
|
||||||
|
Having no file descriptors set is a useful
|
||||||
|
way to sleep the process with sub-second precision by using the timeout.
|
||||||
|
(See further on.)
|
||||||
|
.SS Usleep Emulation
|
||||||
|
On systems that do not have a
|
||||||
|
.BR usleep (3)
|
||||||
|
function, you can call
|
||||||
|
.BR select ()
|
||||||
|
with a finite timeout and no file descriptors as
|
||||||
|
follows:
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 200000; /* 0.2 seconds */
|
||||||
|
select(0, NULL, NULL, NULL, &tv);
|
||||||
|
.fi
|
||||||
|
.PP
|
||||||
|
This is only guaranteed to work on Unix systems, however.
|
||||||
|
.SH EXAMPLE
|
||||||
Here is an example that better demonstrates the true utility of
|
Here is an example that better demonstrates the true utility of
|
||||||
.BR select ().
|
.BR select ().
|
||||||
The listing below is a TCP forwarding program that forwards
|
The listing below is a TCP forwarding program that forwards
|
||||||
|
@ -633,161 +788,6 @@ time, although it could easily be extended to do this with a linked list
|
||||||
of buffers \(em one for each connection.
|
of buffers \(em one for each connection.
|
||||||
At the moment, new
|
At the moment, new
|
||||||
connections cause the current connection to be dropped.
|
connections cause the current connection to be dropped.
|
||||||
.SS Select Law
|
|
||||||
Many people who try to use
|
|
||||||
.BR select ()
|
|
||||||
come across behavior that is
|
|
||||||
difficult to understand and produces non-portable or borderline
|
|
||||||
results.
|
|
||||||
For instance, the above program is carefully written not to
|
|
||||||
block at any point, even though it does not set its file descriptors to
|
|
||||||
non-blocking mode at all (see
|
|
||||||
.BR ioctl (2)).
|
|
||||||
It is easy to introduce
|
|
||||||
subtle errors that will remove the advantage of using
|
|
||||||
.BR select (),
|
|
||||||
hence I will present a list of essentials to watch for when using the
|
|
||||||
.BR select ()
|
|
||||||
call.
|
|
||||||
.TP
|
|
||||||
\fB1.\fP
|
|
||||||
You should always try to use
|
|
||||||
.BR select ()
|
|
||||||
without a timeout.
|
|
||||||
Your program
|
|
||||||
should have nothing to do if there is no data available.
|
|
||||||
Code that
|
|
||||||
depends on timeouts is not usually portable and is difficult to debug.
|
|
||||||
.TP
|
|
||||||
\fB2.\fP
|
|
||||||
The value \fInfds\fP must be properly calculated for efficiency as
|
|
||||||
explained above.
|
|
||||||
.TP
|
|
||||||
\fB3.\fP
|
|
||||||
No file descriptor must be added to any set if you do not intend
|
|
||||||
to check its result after the
|
|
||||||
.BR select ()
|
|
||||||
call, and respond
|
|
||||||
appropriately.
|
|
||||||
See next rule.
|
|
||||||
.TP
|
|
||||||
\fB4.\fP
|
|
||||||
After
|
|
||||||
.BR select ()
|
|
||||||
returns, all file descriptors in all sets
|
|
||||||
should be checked to see if they are ready.
|
|
||||||
.\" mtk, May 2006: the following isn't really true.
|
|
||||||
.\" Any file descriptor that is available
|
|
||||||
.\" for writing \fImust\fP be written to, and any file descriptor
|
|
||||||
.\" available for reading \fImust\fP be read, etc.
|
|
||||||
.TP
|
|
||||||
\fB5.\fP
|
|
||||||
The functions
|
|
||||||
.BR read (2),
|
|
||||||
.BR recv (2),
|
|
||||||
.BR write (2),
|
|
||||||
and
|
|
||||||
.BR send (2)
|
|
||||||
do \fInot\fP necessarily read/write the full amount of data
|
|
||||||
that you have requested.
|
|
||||||
If they do read/write the full amount, its
|
|
||||||
because you have a low traffic load and a fast stream.
|
|
||||||
This is not
|
|
||||||
always going to be the case.
|
|
||||||
You should cope with the case of your
|
|
||||||
functions only managing to send or receive a single byte.
|
|
||||||
.TP
|
|
||||||
\fB6.\fP
|
|
||||||
Never read/write only in single bytes at a time unless your are really
|
|
||||||
sure that you have a small amount of data to process.
|
|
||||||
It is extremely
|
|
||||||
inefficient not to read/write as much data as you can buffer each time.
|
|
||||||
The buffers in the example above are 1024 bytes although they could
|
|
||||||
easily be made larger.
|
|
||||||
.TP
|
|
||||||
\fB7.\fP
|
|
||||||
The functions
|
|
||||||
.BR read (2),
|
|
||||||
.BR recv (2),
|
|
||||||
.BR write (2),
|
|
||||||
and
|
|
||||||
.BR send (2)
|
|
||||||
as well as the
|
|
||||||
.BR select ()
|
|
||||||
call can return \-1 with
|
|
||||||
.I errno
|
|
||||||
set to \fBEINTR\fP,
|
|
||||||
or with
|
|
||||||
.I errno
|
|
||||||
set to \fBEAGAIN\fP (\fBEWOULDBLOCK\fP).
|
|
||||||
These results must be properly managed (not done properly
|
|
||||||
above).
|
|
||||||
If your program is not going to receive any signals then
|
|
||||||
it is unlikely you will get \fBEINTR\fP.
|
|
||||||
If your program does not
|
|
||||||
set non-blocking I/O, you will not get \fBEAGAIN\fP.
|
|
||||||
Nonetheless
|
|
||||||
you should still cope with these errors for completeness.
|
|
||||||
.TP
|
|
||||||
\fB8.\fP
|
|
||||||
Never call
|
|
||||||
.BR read (2),
|
|
||||||
.BR recv (2),
|
|
||||||
.BR write (2),
|
|
||||||
or
|
|
||||||
.BR send (2)
|
|
||||||
with a buffer length of zero.
|
|
||||||
.TP
|
|
||||||
\fB9.\fP
|
|
||||||
If the functions
|
|
||||||
.BR read (2),
|
|
||||||
.BR recv (2),
|
|
||||||
.BR write (2),
|
|
||||||
and
|
|
||||||
.BR send (2)
|
|
||||||
fail
|
|
||||||
with errors other than those listed in \fB7.\fP,
|
|
||||||
or one of the input functions returns 0, indicating end of file,
|
|
||||||
then you should \fInot\fP pass that descriptor to
|
|
||||||
.BR select ()
|
|
||||||
again.
|
|
||||||
In the above example,
|
|
||||||
I close the descriptor immediately, and then set it to \-1
|
|
||||||
to prevent it being included in a set.
|
|
||||||
.TP
|
|
||||||
\fB10.\fP
|
|
||||||
The timeout value must be initialized with each new call to
|
|
||||||
.BR select (),
|
|
||||||
since some operating systems modify the structure.
|
|
||||||
.BR pselect ()
|
|
||||||
however does not modify its timeout structure.
|
|
||||||
.TP
|
|
||||||
\fB11.\fP
|
|
||||||
I have heard that the Windows socket layer does not cope with OOB data
|
|
||||||
properly.
|
|
||||||
It also does not cope with
|
|
||||||
.BR select ()
|
|
||||||
calls when no file
|
|
||||||
descriptors are set at all.
|
|
||||||
Having no file descriptors set is a useful
|
|
||||||
way to sleep the process with sub-second precision by using the timeout.
|
|
||||||
(See further on.)
|
|
||||||
.SS Usleep Emulation
|
|
||||||
On systems that do not have a
|
|
||||||
.BR usleep (3)
|
|
||||||
function, you can call
|
|
||||||
.BR select ()
|
|
||||||
with a finite timeout and no file descriptors as
|
|
||||||
follows:
|
|
||||||
.PP
|
|
||||||
.nf
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 200000; /* 0.2 seconds */
|
|
||||||
select(0, NULL, NULL, NULL, &tv);
|
|
||||||
.fi
|
|
||||||
.PP
|
|
||||||
This is only guaranteed to work on Unix systems, however.
|
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
On success,
|
On success,
|
||||||
.BR select ()
|
.BR select ()
|
||||||
|
|
Loading…
Reference in New Issue