[ Pobierz całość w formacie PDF ]

But seriously, though, there is a danger to using broadcast packets, and that is:
every system that receives a broadcast packet must undo all the onion-skin layers of data
encapsulation until it finds out what port the data is destined to. And then it hands the data
over or discards it. In either case, it's a lot of work for each machine that receives the broadcast
packet, and since it is all of them on the local network, that could be a lot of machines doing a
lot of unnecessary work. When the game Doom first came out, this was a complaint about its
network code.
Yes, I said the local network. There is more than one way to skin a cat... wait a minute. Is
there really more than one way to skin a cat? What kind of expression is that? Uh, and likewise,
there is more than one way to send a broadcast packet, but the broadcast packets will usually be
restricted to your local network no matter how you send them.
So now to the meat and potatoes of the whole thing: how do you specify the destination
address for a broadcast message? There are two common ways.
1. Send the data to your broadcast address. This is your network number with all
one-bits set for the host portion of the address. For instance, at home my network
is 192.168.1.0, my netmask is 255.255.255.0, so the last byte of the address is my
host number (because the first three bytes, according to the netmask, are the network
number). So my broadcast address is 192.168.1.255. Under Unix, the ifconfig
command will actually give you all this data. (If you're curious, the bitwise logic to
get your broadcast address is network_number OR (NOT netmask).)
2. Send the data to the  global broadcast address. This is 255.255.255.255, aka
INADDR_BROADCAST. Many machines will automatically bitwise AND this with
your network number to convert it to a network broadcast address, but some won't. It
varies.
So what happens if you try to send data on the broadcast address without first setting the
SO_BROADCAST socket option? Well, let's fire up good old talker and listener and see what
happens.
$ talker 192.168.1.2 foo
sent 3 bytes to 192.168.1.2
$ talker 192.168.1.255 foo
sendto: Permission denied
$ talker 255.255.255.255 foo
sendto: Permission denied
Yes, it's not happy at all...because we didn't set the SO_BROADCAST socket option. Do that,
and now you can sendto() anywhere you want!
In fact, that's the only difference between a UDP application that can broadcast and one that
can't. So let's take the old talker application and add one section that sets the SO_BROADCAST
socket option. We'll call this program broadcaster.c 28:
/*
** broadcaster.c -- a datagram "client" like talker.c, except
** this one can broadcast
*/
28. http://beej.us/guide/bgnet/examples/broadcaster.c
Beej's Guide to Network Programming 43
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVERPORT 4950 // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int broadcast = 1;
//char broadcast = '1'; // if that doesn't work, try this
if (argc != 3) {
fprintf(stderr,"usage: broadcaster hostname message\n");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
// this call is the difference between this program and talker.c:
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast,
sizeof broadcast) == -1) {
perror("setsockopt (SO_BROADCAST)");
exit(1);
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(SERVERPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0,
(struct sockaddr *)&their_addr, sizeof their_addr)) == -1) {
perror("sendto");
exit(1);
}
printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));
close(sockfd);
return 0;
}
Beej's Guide to Network Programming 44
What's different between this and a  normal UDP client/server situation? Nothing! (With
the exception of the client being allowed to send broadcast packets in this case.) As such, go
ahead and run the old UDP listener program in one window, and broadcaster in another. You
should be now be able to do all those sends that failed, above.
$ talker 192.168.1.2 foo
sent 3 bytes to 192.168.1.2
$ talker 192.168.1.255 foo
sent 3 bytes to 192.168.1.255
$ talker 255.255.255.255 foo
sent 3 bytes to 255.255.255.255
And you should see listener responding that it got the packets.
Well, that's kind of exciting. But now fire up listener on another machine next to you on
the same network so that you have two copies going, one on each machine, and run broadcaster
again with your broadcast address... Hey! Both listeners get the packet even though you only
called sendto() once! Cool!
If the listener gets data you send directly to it, but not data on the broadcast address, it
could be that you have a firewall on your local machine that is blocking the packets. (Yes,
Pat and Bapper, thank you for realizing before I did that this is why my sample code wasn't
working. I told you I'd mention you in the guide, and here you are. So nyah.)
Again, be careful with broadcast packets. Since every machine on the LAN will be forced
to deal with the packet whether it recvfrom()s it or not, it can present quite a load to the entire
computing network. They are definitely to be used sparingly and appropriately.
7. Common Questions
Where can I get those header files?
If you don't have them on your system already, you probably don't need them. Check
the manual for your particular platform. If you're building for Windows, you only need to
#include .
What do I do when bind() reports  Address already in use ?
You have to use setsockopt() with the SO_REUSEADDR option on the listening socket.
Check out the section on bind() and the section on select() for an example.
How do I get a list of open sockets on the system?
Use the netstat. Check the man page for full details, but you should get some good output
just typing:
$ netstat
The only trick is determining which socket is associated with which program. :-)
How can I view the routing table?
Run the route command (in /sbin on most Linuxes) or the command netstat -r.
How can I run the client and server programs if I only have one computer? Don't I need a
network to write network programs?
Fortunately for you, virtually all machines implement a loopback network  device that
sits in the kernel and pretends to be a network card. (This is the interface listed as  lo in the
routing table.)
Pretend you're logged into a machine named  goat . Run the client in one window and
the server in another. Or start the server in the background ( server & ) and run the client in
the same window. The upshot of the loopback device is that you can either client goat or client [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • lastella.htw.pl