网络编程:Linux socket第13部分:多播
中文网站上有大量关于多播服务器和客户端的源代码和详细解释,可是找遍了网络都找不到关于在多网卡环境下怎么指定网卡发送和接收多播消息的说明。于是改用英文在Google上搜索了一下,终于有眉目了。分享给需要的攻城师们。如果有什么问题的大家可以留言。
原文地址:http://www.tenouk.com/Module41c.html
NETWORK PROGRAMMING
LINUX SOCKET PART 13: MULTICAST
Working program examples if any compiled using gcc, tested using the public IPs, run on Linux Fedora 3 with several times update, as normal user. The Fedora machine used for the testing having the "No Stack Execute" disabled and the SELinux set to default configuration. All the program example is generic. Beware codes that expand more than one line.
Example: Sending and receiving a multicast datagram
Example: Sending a multicast datagram, a server program
|
[bodo@bakawali testsocket]$ cat mcastserver.c /* Send Multicast Datagram code example. */ #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h>
struct in_addr localInterface;
struct sockaddr_in groupSock;
int sd;
char databuf[1024] = "Multicast test message lol!";
int datalen = sizeof(databuf);
int main (int argc, char *argv[ ])
{
/* Create a datagram socket on which to send. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
printf("Opening the datagram socket...OK.\n");
/* Initialize the group sockaddr structure with a */
/* group address of 225.1.1.1 and port 5555. */
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("226.1.1.1");
groupSock.sin_port = htons(4321);
/* Disable loopback so you do not receive your own datagrams.
{
char loopch = 0;
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0)
{
perror("Setting IP_MULTICAST_LOOP error");
close(sd);
exit(1);
}
else
printf("Disabling the loopback...OK.\n");
}
*/
/* Set local interface for outbound multicast datagrams. */
/* The IP address specified must be associated with a local, */
/* multicast capable interface. */
localInterface.s_addr = inet_addr("203.106.93.94");
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
exit(1);
}
else
printf("Setting the local interface...OK\n");
/* Send a message to the multicast group specified by the*/
/* groupSock sockaddr structure. */
/*int datalen = 1024;*/
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0)
{perror("Sending datagram message error");}
else
printf("Sending datagram message...OK\n");
/* Try the re-read from the socket if the loopback is not disable
if(read(sd, databuf, datalen) < 0)
{
perror("Reading datagram message error\n");
close(sd);
exit(1);
}
else
{
printf("Reading datagram message from client...OK\n");
printf("The message is: %s\n", databuf);
}
*/
return 0;
}
- Compile and link the program.
[bodo@bakawali testsocket]$ gcc -g mcastserver.c -o mcastserver
- Before running this multicaster program, you have to run the client program first as in the following.
Example: Receiving a multicast datagram, a client
|
/* Receiver/client multicast Datagram example. */ #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> struct sockaddr_in localSock; struct ip_mreq group; int sd; int datalen; char databuf[1024]; int main(int argc, char *argv[]) { /* Create a datagram socket on which to receive. */ sd = socket(AF_INET, SOCK_DGRAM, 0); if(sd < 0) { perror("Opening datagram socket error"); exit(1); } else printf("Opening datagram socket....OK.\n"); /* Enable SO_REUSEADDR to allow multiple instances of this */ /* application to receive copies of the multicast datagrams. */ { int reuse = 1; if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { perror("Setting SO_REUSEADDR error"); close(sd); exit(1); } else printf("Setting SO_REUSEADDR...OK.\n"); } /* Bind to the proper port number with the IP address */ /* specified as INADDR_ANY. */ memset((char *) &localSock, 0, sizeof(localSock)); localSock.sin_family = AF_INET; localSock.sin_port = htons(4321); localSock.sin_addr.s_addr = INADDR_ANY; if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock))) { perror("Binding datagram socket error"); close(sd); exit(1); } else printf("Binding datagram socket...OK.\n"); /* Join the multicast group 226.1.1.1 on the local 203.106.93.94 */ /* interface. Note that this IP_ADD_MEMBERSHIP option must be */ /* called for each local interface over which the multicast */ /* datagrams are to be received. */ group.imr_multiaddr.s_addr = inet_addr("226.1.1.1"); group.imr_interface.s_addr = inet_addr("203.106.93.94"); if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) { perror("Adding multicast group error"); close(sd); exit(1); } else printf("Adding multicast group...OK.\n"); /* Read from the socket. */ datalen = sizeof(databuf); if(read(sd, databuf, datalen) < 0) { perror("Reading datagram message error"); close(sd); exit(1); } else { printf("Reading datagram message...OK.\n"); printf("The message from multicast server is: \"%s\"\n", databuf); } return 0; }
- Compile and link.
[bodo@bakawali testsocket]$ gcc -g mcastclient.c -o mcastclient
- Run the client program.
[bodo@bakawali testsocket]$ ./mcastclient
Opening datagram socket....OK.
Setting SO_REUSEADDR...OK.
Binding datagram socket...OK.
Adding multicast group...OK.
- Then run the server program.
[bodo@bakawali testsocket]$ ./mcastserver
Opening the datagram socket...OK.
Setting the local interface...OK
Sending datagram message...OK
[bodo@bakawali testsocket]$
- The messages on the client console are shown below.
[bodo@bakawali testsocket]$ ./mcastclient
Opening datagram socket....OK.
Setting SO_REUSEADDR...OK.
Binding datagram socket...OK.
Adding multicast group...OK.
Reading datagram message...OK.
The message from multicast server is: "Multicast test message lol!"
[bodo@bakawali testsocket]$