#Header1_HeaderTitle{ font-size:50px }

UDP广播的客户端和服务器端的代码设计

实验环境

linux

注意:

使用UDP广播,是客户端发送广播消息,服务器端接收消息。实际上是客户端探测局域网中可用服务器的一种手段。客户端发送,服务器端接收,千万不能弄混淆!!!

为了避免混淆,本文不使用client、server字眼。而使用send,recv

构建send_broadcast.c。发送广播消息,并打印接收端的IP和端口,退出时发送"done"消息

流程:创建一个socket,并用setscokopt函数声明这是一个broadcast类型的socket,然后通过这个socket向INADDR_BROADCAST("255.255.255.255")发送消息。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define PORT 1234
#define BUFFER_SIZE 100

int32_t main()
{
    char msg[BUFFER_SIZE] = "I am a broadcast message";
    int32_t nb = 0; 
    struct sockaddr_in addrto;    
    int32_t nlen=sizeof(addrto); 

    int32_t sockfd = -1;  
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)   
    {     
        perror("create socket failed\n");   
        return -1;  
    }    

    const int opt = 1;  
    //设置该套接字为广播类型,  
    nb = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &opt, sizeof(opt));  
    if(nb == -1)  
    {  
        perror("set socket error...\n");  
        return -1;  
    }  

    /**< 接收者地址结构 */
    bzero(&addrto, sizeof(struct sockaddr_in));  
    addrto.sin_family = AF_INET;    
    addrto.sin_addr.s_addr = htonl(INADDR_BROADCAST);  
    addrto.sin_port = htons(PORT);  
  
    int ret = sendto(sockfd, msg, BUFFER_SIZE, 0, (struct sockaddr*)&addrto, nlen);  
    if (ret < 0)  
    {  
        perror("send error.\n");  
    } 

    /**< 打印接收者的IP和端口号 */
    printf("recver's ip is %s, port is %d.\n", inet_ntoa(addrto.sin_addr), htons(addrto.sin_port));

    bzero(msg, BUFFER_SIZE);
    memcpy(msg, "done", 5);

    sendto(sockfd, msg, BUFFER_SIZE, 0, (struct sockaddr*)&addrto, nlen);
    
    printf("Done\n");
    return 0;  
}  

构建recv_broadcast.c 接收广播消息,打印发送端的IP和端口号,在接收到done后停止并退出

流程:创建一个socket并绑定INADDR_ANY的本地地址,接收消息

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
  
#define PORT 1234
#define BUFFER_SIZE 100

int32_t main()
{
    struct sockaddr_in addrto;
    
    struct sockaddr_in from;
    int32_t listenfd = -1;
    int32_t len = sizeof(from);
    char recvbuf[BUFFER_SIZE];

    if ((listenfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)   
    {     
        perror("create socket failed\n");   
        return -1;  
    } 
    
    bzero(&addrto, sizeof(struct sockaddr_in));  
    bzero(&from, sizeof(struct sockaddr_in));  
    addrto.sin_family = AF_INET;
    addrto.sin_port = htons(PORT);  
    addrto.sin_addr.s_addr = htonl(INADDR_ANY);  

    const int opt = 1;  
    int32_t nb = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  
    if(nb == -1)  
    {  
        perror("set socket error...\n");  
        return -1;  
    }  

    /**< 绑定自己的地址 */
    if (bind(listenfd, (struct sockaddr *)&addrto, len) == -1)
    {
        perror("bind error\n");
        return -1;
    }

    while (1)
    {
        //从广播地址接收消息  
        int ret = recvfrom(listenfd, recvbuf, BUFFER_SIZE, 0, (struct sockaddr*)&from, &len);  
        if (ret > 0)  
        {  
            recvbuf[ret] = '\0';
            printf("receive messgse:%s\n", recvbuf);
            if (!strcmp("done", recvbuf))
            {
                break;
            }
        }  
        else  
        {    
            perror("recv error.\n");  

        } 
        bzero(recvbuf, BUFFER_SIZE);

        /**< 打印发送者的ip和端口号 */
        printf("sender's ip is %s, port is %d.\n", inet_ntoa(from.sin_addr), htons(from.sin_port));
    }

    close(listenfd);
    printf("Done\n");
    return 0;  
}  

 Makefile

all:sender recver
sender:
    gcc send_broadcast.c -o sender

recver:
    gcc recv_broadcast.c -o recver

clean:
    rm -rf sender recver

 

posted @ 2020-04-11 09:41  墨麟非攻  阅读(964)  评论(0编辑  收藏  举报