📄 5.t
字号:
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));.DEwhere \f2loop\f1 is set to 0 to disable loopback,and set to 1 to enable loopback.This optionimproves performance for applications that may have no more than oneinstance on a single host (such as a router demon), by eliminatingthe overhead of receiving their own transmissions. It should generally notbe used by applications for which there may be more than one instance on asingle host (such as a conferencing program) or for which the sender doesnot belong to the destination group (such as a time querying program)..PPA multicast datagram sent with an initial TTL greater than 1 may be deliveredto the sending host on a different interface from that on which it was sent,if the host belongs to the destination group on that other interface. Theloopback control option has no effect on such delivery..NH 3 Receiving IP Multicast Datagrams.PPBefore a host can receive IP multicast datagrams, it must become a memberof one or more IP multicast groups. A process can ask the host to joina multicast group by using the following socket option:.DSstruct ip_mreq mreq;setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)).DEwhere "mreq" is the following structure:.DSstruct ip_mreq { struct in_addr imr_multiaddr; /* \fImulticast group to join\fP */ struct in_addr imr_interface; /* \fIinterface to join on\fP */}.DEEvery membership is associated with a single interface, and it is possibleto join the same group on more than one interface. "imr_interface" shouldbe INADDR_ANY to choose the default multicast interface, or one of thehost's local addresses to choose a particular (multicast-capable) interface.Up to IP_MAX_MEMBERSHIPS (currently 20) memberships may be added on asingle socket..PPTo drop a membership, use:.DSstruct ip_mreq mreq;setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));.DEwhere "mreq" contains the same values as used to add the membership. Thememberships associated with a socket are also dropped when the socket isclosed or the process holding the socket is killed. However, more thanone socket may claim a membership in a particular group, and the hostwill remain a member of that group until the last claim is dropped..PPThe memberships associated with a socket do not necessarily determine whichdatagrams are received on that socket. Incoming multicast packets areaccepted by the kernel IP layer if any socket has claimed a membership in thedestination group of the datagram; however, delivery of a multicast datagramto a particular socket is based on the destination port (or protocol type, forraw sockets), just as with unicast datagrams. To receive multicast datagramssent to a particular port, it is necessary to bind to that local port,leaving the local address unspecified (i.e., INADDR_ANY).To receive multicast datagramssent to a particular group and port, bind to the local port, withthe local address set to the multicast group address. Once bound to a multicast address, the socket cannot be used for sending data..PPMore than one process may bind to the same SOCK_DGRAM UDP port or the same multicast group and port if the.I bindcall is preceded by:.DSint on = 1;setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));.DEAll processes sharing the port must enable this option.Every incoming multicast or broadcast UDP datagram destined tothe shared port is delivered to all sockets bound to the port. For backwards compatibility reasons, this does not apply to incomingunicast datagrams. Unicastdatagrams are never delivered to more than one socket, regardless ofhow many sockets are bound to the datagram's destination port..PPA final multicast-related extension is independent of IP: two new ioctls,SIOCADDMULTI and SIOCDELMULTI, are available to add or delete link-level(e.g., Ethernet) multicast addresses accepted by a particular interface.The address to be added or deleted is passed as a sockaddr structure offamily AF_UNSPEC, within the standard ifreq structure..PPThese ioctls arefor the use of protocols other than IP, and require superuser privileges.A link-level multicast address added via SIOCADDMULTI is not automaticallydeleted when the socket used to add it goes away; it must be explicitlydeleted. It is inadvisable to delete a link-level address that may bein use by IP..NH 3Sample Multicast Program.PPThe following program sends or receives multicast packets.If invoked with one argument, it sends a packet containing the currenttime to an arbitrarily-chosen multicast group and UDP port.If invoked with no arguments, it receives and prints these packets.Start it as a sender on just one host and as a receiver on all the other hosts..DS#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <time.h>#include <stdio.h>#define EXAMPLE_PORT 60123#define EXAMPLE_GROUP "224.0.0.250"main(argc) int argc;{ struct sockaddr_in addr; int addrlen, fd, cnt; struct ip_mreq mreq; char message[50]; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket"); exit(1); } bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(EXAMPLE_PORT); addrlen = sizeof(addr); if (argc > 1) { /* Send */ addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP); while (1) { time_t t = time(0); sprintf(message, "time is %-24.24s", ctime(&t)); cnt = sendto(fd, message, sizeof(message), 0, (struct sockaddr *)&addr, addrlen); if (cnt < 0) { perror("sendto"); exit(1); } sleep(5); } } else { /* Receive */ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); exit(1); } mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { perror("setsockopt mreq"); exit(1); } while (1) { cnt = recvfrom(fd, message, sizeof(message), 0, (struct sockaddr *)&addr, &addrlen); if (cnt <= 0) { if (cnt == 0) { break; } perror("recvfrom"); exit(1); } printf("%s: message = \e"%s\e"\en", inet_ntoa(addr.sin_addr), message); } }}.DE.\"----------------------------------------------------------------------.NH 2NS Packet Sequences.PPThe semantics of NS connections demand thatthe user both be able to look inside the network header associatedwith any incoming packet and be able to specify what should goin certain fields of an outgoing packet.Using different calls to \fIsetsockopt\fP, it is possibleto indicate whether prototype headers will be associated bythe user with each outgoing packet (SO_HEADERS_ON_OUTPUT),to indicate whether the headers received by the system should bedelivered to the user (SO_HEADERS_ON_INPUT), or to indicatedefault information that should be associated with alloutgoing packets on a given socket (SO_DEFAULT_HEADERS)..PPThe contents of a SPP header (minus the IDP header) are:.DS.if t .ta \w" #define"u +\w" u_short"u +2.0istruct sphdr { u_char sp_cc; /* connection control */#define SP_SP 0x80 /* system packet */#define SP_SA 0x40 /* send acknowledgement */#define SP_OB 0x20 /* attention (out of band data) */#define SP_EM 0x10 /* end of message */ u_char sp_dt; /* datastream type */ u_short sp_sid; /* source connection identifier */ u_short sp_did; /* destination connection identifier */ u_short sp_seq; /* sequence number */ u_short sp_ack; /* acknowledge number */ u_short sp_alo; /* allocation number */};.DEHere, the items of interest are the \fIdatastream type\fP andthe \fIconnection control\fP fields. The semantics of thedatastream type are defined by the application(s) in question;the value of this field is, by default, zero, but it can beused to indicate things such as Xerox's Bulk Data TransferProtocol (in which case it is set to one). The connection controlfield is a mask of the flags defined just below it. The user mayset or clear the end-of-message bit to indicatethat a given message is the last of a given substream type,or may set/clear the attention bit as an alternate way toindicate that a packet should be sent out-of-band.As an example, to associate prototype headers with outgoingSPP packets, consider:.DS#include <sys/types.h>#include <sys/socket.h>#include <netns/ns.h>#include <netns/sp.h> ...struct sockaddr_ns sns, to;int s, on = 1;struct databuf { struct sphdr proto_spp; /* prototype header */ char buf[534]; /* max. possible data by Xerox std. */} buf; ...s = socket(AF_NS, SOCK_SEQPACKET, 0); ...bind(s, (struct sockaddr *) &sns, sizeof (sns));setsockopt(s, NSPROTO_SPP, SO_HEADERS_ON_OUTPUT, &on, sizeof(on)); ...buf.proto_spp.sp_dt = 1; /* bulk data */buf.proto_spp.sp_cc = SP_EM; /* end-of-message */strcpy(buf.buf, "hello world\en");sendto(s, (char *) &buf, sizeof(struct sphdr) + strlen("hello world\en"), (struct sockaddr *) &to, sizeof(to)); ....DENote that one must be careful when writing headers; if the prototypeheader is not written with the data with which it is to be associated,the kernel will treat the first few bytes of the data as theheader, with unpredictable results.To turn off the above association, and to indicate that packetheaders received by the system should be passed up to the user,one might use:.DS#include <sys/types.h>#include <sys/socket.h>#include <netns/ns.h>#include <netns/sp.h> ...struct sockaddr sns;int s, on = 1, off = 0; ...s = socket(AF_NS, SOCK_SEQPACKET, 0); ...bind(s, (struct sockaddr *) &sns, sizeof (sns));setsockopt(s, NSPROTO_SPP, SO_HEADERS_ON_OUTPUT, &off, sizeof(off));setsockopt(s, NSPROTO_SPP, SO_HEADERS_ON_INPUT, &on, sizeof(on)); ....DE.PPOutput is handled somewhat differently in the IDP world.The header of an IDP-level packet looks like:.DS.if t .ta \w'struct 'u +\w" struct ns_addr"u +2.0istruct idp { u_short idp_sum; /* Checksum */ u_short idp_len; /* Length, in bytes, including header */ u_char idp_tc; /* Transport Control (i.e., hop count) */ u_char idp_pt; /* Packet Type (i.e., level 2 protocol) */ struct ns_addr idp_dna; /* Destination Network Address */ struct ns_addr idp_sna; /* Source Network Address */};.DEThe primary field of interest in an IDP header is the \fIpacket type\fPfield. The standard values for this field are (as definedin <\fInetns/ns.h\fP>):.DS.if t .ta \w" #define"u +\w" NSPROTO_ERROR"u +1.0i#define NSPROTO_RI 1 /* Routing Information */#define NSPROTO_ECHO 2 /* Echo Protocol */#define NSPROTO_ERROR 3 /* Error Protocol */#define NSPROTO_PE 4 /* Packet Exchange */#define NSPROTO_SPP 5 /* Sequenced Packet */.DEFor SPP connections, the contents of this field areautomatically set to NSPROTO_SPP; for IDP packets,this value defaults to zero, which means ``unknown''..PPSetting the value of that field with SO_DEFAULT_HEADERS iseasy:.DS#include <sys/types.h>#include <sys/socket.h>#include <netns/ns.h>#include <netns/idp.h> ...struct sockaddr sns;struct idp proto_idp; /* prototype header */int s, on = 1; ...s = socket(AF_NS, SOCK_DGRAM, 0); ...bind(s, (struct sockaddr *) &sns, sizeof (sns));proto_idp.idp_pt = NSPROTO_PE; /* packet exchange */setsockopt(s, NSPROTO_IDP, SO_DEFAULT_HEADERS, (char *) &proto_idp, sizeof(proto_idp)); ....DE.PPUsing SO_HEADERS_ON_OUTPUT is somewhat more difficult. WhenSO_HEADERS_ON_OUTPUT is turned on for an IDP socket, the socketbecomes (for all intents and purposes) a raw socket. In thiscase, all the fields of the prototype header (except the length and checksum fields, which are computed by the kernel)must be filled in correctly in order for the socket to send andreceive data in a sensible manner. To be more specific, thesource address must be set to that of the host sending thedata; the destination address must be set to that of thehost for whom the data is intended; the packet type must beset to whatever value is desired; and the hopcount must beset to some reasonable value (almost always zero). It shouldalso be noted that simply sending data using \fIwrite\fPwill not work unless a \fIconnect\fP or \fIsendto\fP callis used, in spite of the fact that it is the destination
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -