- 论坛徽章:
- 0
|
以下是gnu/linux 编程指南中关于多播IP的两个列子,
1.设置过route后运行时
broadcast没问题.
listen端会出现setsockopt(allow multiple socket use): Invalid argument //看书上和man里函数原型,没发现错在哪
listen端只能有一个进程,在开一个时,会出现call to bind: Address already in use后停在那了
在setsockopt中不是设置过SO_REUSEADDR么,以允许一个给定的地址可在同一台计算机上同时被一个以上的进程使用????
/* broadcast.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
* route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int port = 6789;
void main() {
int socket_descriptor;
struct sockaddr_in address;
// For broadcasting, this socket can be treated like a UDP socket:
socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_descriptor == -1) {
perror("Opening socket"
exit(1);
}
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("224.0.0.1"
address.sin_port = htons(port);
while (1) {
if (sendto(socket_descriptor,
"test from broadcast Q", sizeof("test from broadcast Q",
0, (struct sockaddr *)&address, sizeof(address))
< 0) {
perror("Trying to broadcast with sendto"
exit(1);
}
sleep(2);
}
}
/* listen.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
* route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
char *host_name = "224.0.0.1"; // local host (multicast IP)
int port = 6789;
int main() {
struct ip_mreq command;
u_char loop = 1; // we want broadcast to also loop back to this computer
int iter = 0;
int sin_len;
char message[256];
int socket_descriptor;
struct sockaddr_in sin;
struct hostent *server_host_name;
char * str = "A default test string";
if ((server_host_name = gethostbyname(host_name)) == 0) {
perror("Error resolving local host\n"
exit(1);
}
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
//if ((socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
if ((socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error opening socket\n"
exit(1);
}
// allow multiple processes to use this same port???????
/*
setsockopt(allow multiple socket use): Invalid argument
call to bind: Address already in use???????
*/
loop = 1;
// u_char share = 1;
if (setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
&loop, sizeof(loop)) < 0) { ////Invalid argument?????
perror("setsockopt(allow multiple socket use)"
}
if (bind(socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("call to bind" //Address already in use?????
}
// allow broadcast to this machine"
loop = 1;
if (setsockopt(socket_descriptor, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, sizeof(loop)) < 0) {
perror("setsockopt(multicast loop on)"
}
// join the broadcast group:
command.imr_multiaddr.s_addr = inet_addr("224.0.0.1"
command.imr_interface.s_addr = htonl(INADDR_ANY);
if (command.imr_multiaddr.s_addr == -1) {
printf("Error: group of 224.0.0.1 not a legal multicast address\n");
}
if (setsockopt(socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&command, sizeof(command)) < 0) {
perror("Error in setsocket(add membership)");
}
while (iter++ < 10) {
sin_len = sizeof(sin);
if (recvfrom(socket_descriptor, message, 256, 0,
(struct sockaddr *)&sin, &sin_len) == -1) {
perror("Error in receiving response from server\n");
}
printf("\nResponse from server:\n\n%s\n", message);
sleep(2);
}
// leave the broadcast group ('struct ip_mreq command' is still setup OK):
if (setsockopt(socket_descriptor, IPPROTO_IP, IP_DROP_MEMBERSHIP,
&command, sizeof(command)) < 0) {
perror("Error in setsocket(drop membership)");
}
close(socket_descriptor);
}
2.这个程序可以同时运行多多次,但只有一个能接收到所有发送的消息,另外的只能发送,不能接收到.
/* nb_broadcast_and_listen.c
* Copyright Mark Watson 1999. Open Source Software License.
*
* Sample broadcast using Multicast IP and non-blocking sockets.
* You must rebuild your Linux kernel to support Multicast IP
* and you have to issue something like this (as root):
* route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
*
* Note: this example was derived from the multicast IP broadcast
* example, and is very similar.
*/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
int port = 9876;
char * host_name = "224.0.0.1"; // local host (multicast IP)
int main() {
// for setting up for broadcast:
int out_socket_descriptor;
struct sockaddr_in address;
// for setting up for listening for broadcasts
struct ip_mreq command;
u_char loop = 1; // we want broadcast to also loop back to this computer
int i, iter = 0;
int sin_len;
char message[256];
int in_socket_descriptor;
struct sockaddr_in sin;
struct hostent *server_host_name;
struct sockaddr_in gsin;
int gsin_len;
long save_file_flags;
// For broadcasting, this socket can be treated like a UDP socket:
out_socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0);
if (out_socket_descriptor == -1) {
perror("Opening socket");
exit(1);
}
// allow multiple processes to use this same port:
loop = 1;
if (setsockopt(out_socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
&loop, sizeof(loop)) < 0) {
perror("setsockopt(allow multiple socket use)");
printf("errno =%d\n",errno);
}
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("224.0.0.1");
address.sin_port = htons(port);
// Set up for listening:
if ((server_host_name = gethostbyname(host_name)) == 0) {
perror("Error resolving local host\n");
exit(1);
}
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
//if ((in_socket_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
if ((in_socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error opening socket\n");
exit(1);
}
// allow multiple processes to use this same port:
loop = 1;
if (setsockopt(in_socket_descriptor, SOL_SOCKET, SO_REUSEADDR,
&loop, sizeof(loop)) < 0) {
perror("setsockopt(allow multiple socket use:2)");
printf("errno =%d\n",errno);
}
if (bind(in_socket_descriptor, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("call to bind");
}
// allow broadcast to this machine"
loop = 1;
if (setsockopt(in_socket_descriptor, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, sizeof(loop)) < 0) {
perror("setsockopt(multicast loop on)");
}
// join the broadcast group:
command.imr_multiaddr.s_addr = inet_addr("224.0.1.1");
command.imr_interface.s_addr = htonl(INADDR_ANY);
// command.imr_interface.s_addr = htonl("127.0.0.1");
if (command.imr_multiaddr.s_addr == -1) {
printf("Error: group of 224.0.0.1 not a legal multicast address\n");
}
if (setsockopt(in_socket_descriptor, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&command, sizeof(command)) < 0) {
perror("Error in setsocket(add membership)");
}
// set socket to non-blocking:
save_file_flags = fcntl(in_socket_descriptor, F_GETFL); //get!
printf("file flags=%ld\n", save_file_flags);
save_file_flags |= O_NONBLOCK;
if (fcntl(in_socket_descriptor, F_SETFL, save_file_flags) < 0) { //set!
perror("trying to set input socket to non-blocking");
}
printf("after setting non-blocking,file flags=%ld\n", save_file_flags);
// main loop that both broadcasts and listens:
printf("Staring main loop to broadcast and listen...\n");
while (iter++ < 20) {
printf("%d iteration\n", iter);
if ((iter % 7) == 0) { // do a broadcast every 7 times through loop
printf("sending data...\n");
if (sendto(out_socket_descriptor,
"test from broadcast", sizeof("test from broadcast"),
0, (struct sockaddr *)&address, sizeof(address))
< 0) {
perror("Trying to broadcast with sendto");
exit(1);
}
}
sleep(1); // wait a second
// see if there is any data to read on the non-blocking socket:
gsin_len = sizeof(gsin);
i = recvfrom(in_socket_descriptor, message, 256, 0,
(struct sockaddr *)&gsin, &gsin_len); //sin???
if (i > 0) {
printf("Response from server:%s\n", message);
} else {
printf("No data available to read\n");
}
}
} |
|