23.广播

如果想发送广播到目前为止只能使用AF_INET, SOCK_DGRAM,也就是说只能采用基于IPV4的UDP协议才能发送广播。

IP地址有32位组成,如果想向某个网段发送广播,只需要那个发送的IP地址的主机号改成全1即可。比如大家最常用的局域网内部广播,我的网络地址为192.168.1.xxx。因此我只需要发送地址改为192.168.1.255.另外路由不转发广播,也就是说:处于192.168.1.xxx网段的广播是不会发送到192.168.2.xxx网段上。这也是说主机192.168.1.221如果想发送192.168.2.xxx的广播是行不通的。

代码就很简单的,但是有点要注意的是:必须通过套接口选项SO_BROADCAST设置,明确的告诉路由,你要发送的是广播,不然是无法发送出去。

发送代码:

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/select.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        int maxfdpl;
        char send[] = "hello world";

        if(argc != 2) {
                printf("please input port");
                exit(1);
        }

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);/发送广播,必须采用AF_INET,SOCK_DGRAM才可以
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_port = htons(atoi(argv[1]));

        const int on = 1;
        setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));//设置套接口选项SO_BROADCAST明确告诉路由发送的是广播

        inet_pton(AF_INET, "192.168.1.255", &serv_socket.sin_addr);
        int temp = sendto(sockfd, send, sizeof(send), 0, (struct sockaddr *)&serv_socket, sizeof(struct sockaddr_in));
        if(temp == -1)
                printf("system message:send failed\n");
}

接受代码:

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/wait.h"
#include "sys/select.h"
#include "sys/poll.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd;
        struct sockaddr_in serv_socket;
        struct sockaddr_in * client_socket = NULL;
        char send[MAXSIZE + 1];
        char recv[MAXSIZE + 1];

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        bzero(&serv_socket, sizeof(serv_socket));
        serv_socket.sin_family = AF_INET;
        serv_socket.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_socket.sin_port = htons(atoi(argv[1]));
        bind(sockfd, (struct sockaddr *)&serv_socket, sizeof(serv_socket));
        socklen_t len = sizeof(client_socket);
        client_socket = (struct sockaddr_in *) malloc (sizeof(struct sockaddr_in));

        int n = recvfrom(sockfd, recv, MAXSIZE, 0, (struct sockaddr *)client_socket, &len);
        recv[n] = '\0';
        printf("client message:%s\n", recv);
}

另外唯一要注意的是:发送的广播时候传输的数据不应过长,因为广播的是不会被分片,也就是说如果超过了MTU,数据包会被丢弃。不分片的原因是因为设计者认为广播已经给网络带来了很大的负担,没必要再通过分片将这种负担扩大数倍。

另外,高层的SOCKET也会处理,至少在我所执行的fedora环境下,当我试图把发送的内容buf扩大至10000个字符时候,并没有出现因不分片而导致的错误,接受端仍然接受到了数据,不过数据是被截断后的数据(要远远小于10000个字符),我怀疑原因:可能是linux内核在发现要发送广播,而数据又过长需要分片的时候,直接将数据截断变成无需分片的大小。

猜你喜欢

转载自memorymyann.iteye.com/blog/656321
今日推荐