, Beej's Gu 

[ Pobierz całość w formacie PDF ]

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
FD_SET(int fd, fd_set *set);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
Description
The select() function gives you a way to simultaneously check multiple sockets to see if
they have data waiting to be recv()d, or if you can send() data to them without blocking, or
if some exception has occurred.
You populate your sets of socket descriptors using the macros, like FD_SET(), above.
Once you have the set, you pass it into the function as one of the following parameters:
readfds if you want to know when any of the sockets in the set is ready to recv() data,
writefds if any of the sockets is ready to send() data to, and/or exceptfds if you need to
know when an exception (error) occurs on any of the sockets. Any or all of these parameters
can be NULL if you're not interested in those types of events. After select() returns, the values
in the sets will be changed to show which are ready for reading or writing, and which have
exceptions.
The first parameter, n is the highest-numbered socket descriptor (they're just ints,
remember?) plus one.
Lastly, the struct timeval, timeout, at the end this lets you tell select() how long
to check these sets for. It'll return after the timeout, or when an event occurs, whichever is first.
The struct timeval has two fields: tv_sec is the number of seconds, to which is added
tv_usec, the number of microseconds (1,000,000 microseconds in a second.)
The helper macros do the following:
FD_SET(int fd, fd_set *set); Add fd to the set.
FD_CLR(int fd, fd_set *set); Remove fd from the set.
FD_ISSET(int fd, fd_set *set); Return true if fd is in the set.
FD_ZERO(fd_set *set); Clear all entries from the set.
Return Value
Returns the number of descriptors in the set on success, 0 if the timeout was reached, or -1
on error (and errno will be set accordingly.) Also, the sets are modified to show which sockets
are ready.
Example
int s1, s2, n;
fd_set readfds;
struct timeval tv;
char buf1[256], buf2[256];
s1 = socket(PF_INET, SOCK_STREAM, 0);
Beej's Guide to Network Programming 73
s2 = socket(PF_INET, SOCK_STREAM, 0);
// pretend we've connected both to a server at this point
//connect(s1, ...)...
//connect(s2, ...)...
// clear the set ahead of time
FD_ZERO(&readfds);
// add our descriptors to the set
FD_SET(s1, &readfds);
FD_SET(s2, &readfds);
// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
n = s2 + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 10;
tv.tv_usec = 500000;
rv = select(n, &readfds, NULL, NULL, &tv);
if (rv == -1) {
perror("select"); // error occurred in select()
} else if (rv == 0) {
printf("Timeout occurred! No data after 10.5 seconds.\n");
} else {
// one or both of the descriptors have data
if (FD_ISSET(s1, &readfds)) {
recv(s1, buf1, sizeof buf1, 0);
}
if (FD_ISSET(s2, &readfds)) {
recv(s1, buf2, sizeof buf2, 0);
}
}
See Also
poll()
Beej's Guide to Network Programming 74
8.17. setsockopt(), getsockopt()
Set various options for a socket
Prototypes
#include
#include
int getsockopt(int s, int level, int optname, void *optval,
socklen_t *optlen);
int setsockopt(int s, int level, int optname, const void *optval,
socklen_t optlen);
Description
Sockets are fairly configurable beasts. In fact, they are so configurable, I'm not even going
to cover it all here. It's probably system-dependent anyway. But I will talk about the basics.
Obviously, these functions get and set certain options on a socket. On a Linux box, all the
socket information is in the man page for socket in section 7. (Type:  man 7 socket to get all
these goodies.)
As for parameters, s is the socket you're talking about, level should be set to SOL_SOCKET.
Then you set the optname to the name you're interested in. Again, see your man page for all the
options, but here are some of the most fun ones:
SO_BINDTODEVICE Bind this socket to a symbolic device name like eth0 instead
of using bind() to bind it to an IP address. Type the command
ifconfig under Unix to see the device names.
SO_REUSEADDR Allows other sockets to bind() to this port, unless there is an
active listening socket bound to the port already. This enables
you to get around those  Address already in use error messages
when you try to restart your server after a crash.
SO_BROADCAST Allows UDP datagram (SOCK_DGRAM) sockets to send and
receive packets sent to and from the broadcast address. Does
nothing NOTHING!! to TCP stream sockets! Hahaha!
As for the parameter optval, it's usually a pointer to an int indicating the value in
question. For booleans, zero is false, and non-zero is true. And that's an absolute fact, unless it's
different on your system. If there is no parameter to be passed, optval can be NULL.
The final parameter, optlen, is filled out for you by getsockopt() and you have to
specify it for getsockopt(), where it will probably be sizeof(int).
Warning: on some systems (notably Sun and Windows), the option can be a char instead
of an int, and is set to, for example, a character value of '1' instead of an int value of 1.
Again, check your own man pages for more info with  man setsockopt and  man 7 socket !
Return Value
Returns zero on success, or -1 on error (and errno will be set accordingly.)
Example
int optval;
int optlen;
char *optval2;
// set SO_REUSEADDR on a socket to true (1):
optval = 1;
Beej's Guide to Network Programming 75
setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
// bind a socket to a device name (might not work on all systems):
optval2 = "eth1"; // 4 bytes long, so 4, below:
setsockopt(s2, SOL_SOCKET, SO_BINDTODEVICE, optval2, 4);
// see if the SO_BROADCAST flag is set:
getsockopt(s3, SOL_SOCKET, SO_BROADCAST, &optval, &optlen);
if (optval != 0) {
print("SO_BROADCAST enabled on s3!\n");
}
See Also
fcntl()
Beej's Guide to Network Programming 76
8.18. send(), sendto()
Send data out over a socket
Prototypes
#include
#include
ssize_t send(int s, const void *buf, size_t len, int flags);
ssize_t sendto(int s, const void *buf, size_t len,
int flags, const struct sockaddr *to,
socklen_t tolen);
Description
These functions send data to a socket. Generally speaking, send() is used for TCP
SOCK_STREAM connected sockets, and sendto() is used for UDP SOCK_DGRAM unconnected
datagram sockets. With the unconnected sockets, you must specify the destination of a packet
each time you send one, and that's why the last parameters of sendto() define where the
packet is going.
With both send() and sendto(), the parameter s is the socket, buf is a pointer to the
data you want to send, len is the number of bytes you want to send, and flags allows you to
specify more information about how the data is to be sent. Set flags to zero if you want it to be
 normal data. Here are some of the commonly used flags, but check your local send() man
pages for more details:
MSG_OOB Send as  out of band data. TCP supports this, and it's a way to
tell the receiving system that this data has a higher priority than [ Pobierz całość w formacie PDF ]
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • osy.pev.pl