Linux网络编程-UDP单播服务客户端代码实现

目录

一、UDP单播介绍

1.UDP介绍        

2.单播简介

3.单播的优点:

4.单播的缺点:

二、UDP单播编程

1.创建套接字-socket

2.发送数据-sendto

3.绑定-bind

4.接受数据-recvfrom

三、UDP单播服务端代码实现

1.代码分析

2.运行结果

3.UDP单播服务器注意点

四、UDP单播服务端代码实现

1.代码分析

2.运行结果

3.UDP单播客户端注意点


一、UDP单播介绍

1.UDP介绍        

        UDP协议进行信息的传输之前不需要建议连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。更多UDP详细介绍可以查看:Linux网络编程-UDP协议详解

2.单播简介

    主机之间一对一的通讯模式,网络中的交换机和路由器对数据只进行转发不进行复制。如果10个客户机需要相同的数据,则服务器需要逐一传送,重复10次相同的工作。但由于其能够针对每个客户的及时响应,所以现在的网页浏览全部都是采用单播模式,具体的说就是IP单播协议。网络中的路由器和交换机根据其目标地址选择传输路径,将IP单播数据传送到其指定的目的地。

3.单播的优点:

     1)服务器及时响应客户机的请求
     2)服务器针对每个客户不通的请求发送不通的数据,容易实现个性化服务。

4.单播的缺点:

    1)服务器针对每个客户机发送数据流,服务器流量=客户机数量×客户机流量;在客户数量大、每个客户机流量大的流媒体应用中服务器不堪重负。
     2)现有的网络带宽是金字塔结构,城际省际主干带宽仅仅相当于其所有用户带宽之和的5%。如果全部使用单播协议,将造成网络主干不堪重负。现在的P2P应用就已经使主干经常阻塞。而将主干扩展20倍几乎是不可能。

二、UDP单播编程

1.创建套接字-socket

        int socket(int family,int type,int protocol);

 功能: 

    创建一个用于网络通信的socket套接字(描述符)
参数:
    family:协议族(AF_INET、AF_INET6、PF_PACKET等)
    type:套接字类(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW等)
    protocol:协议类别(0、IPPROTO_TCP、IPPROTO_UDP等
返回值:套接字
特点:
    创建套接字时,系统不会分配端口
    创建的套接字默认属性是主动的,即主动发起服务的请求;当作为服务器时,往往需要修改为被动的
头文件:#include <sys/socket.h>

2.发送数据-sendto

ssize_t sendto(int sockfd,const void *buf,size_t nbytes,int flags,const struct sockaddr *to,
socklen_t addrlen);

功能:
     向to结构体指针中指定的ip,发送UDP数据
参数:
    sockfd:套接字
    buf: 发送数据缓冲区
    nbytes: 发送数据缓冲区的大小
    flags:一般为0
    to: 指向目的主机地址结构体的指针
    addrlen:to所指向内容的长度

注意
    通过to和addrlen确定目的地址
    可以发送0长度的UDP数据包
返回值
    成功:发送数据的字符数
    失败: -1


3.绑定-bind

int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);

功能:将本地协议地址与sockfd绑定
参数
    sockfd: socket套接字
    myaddr: 指向特定协议的地址结构指针
    addrlen:该地址结构的长度
返回值
    成功:返回0
    失败:其他

4.接受数据-recvfrom

 ssize_t recvfrom(int sockfd, void *buf,size_t nbytes,int flags,struct sockaddr *from,
socklen_t *addrlen);

功能
    接收UDP数据,并将源地址信息保存在from指向的结构中

参数
    sockfd:套接字
    buf: 接收数据缓冲区
    nbytes:接收数据缓冲区的大小

    flags: 套接字标志(常为0)
    from: 源地址结构体指针,用来保存数据的来源
    addrlen: from所指内容的长度
注意:
    通过from和addrlen参数存放数据来源信息
    from和addrlen可以为NULL, 表示不保存数据来源
返回值:
    成功:接收到的字符数
   失败: -1

三、UDP单播服务端代码实现

1.代码分析

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

#define BUF_SIZE 88
#define PORT     55555

int main(int argc, char *argv[])
{
    //建立套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);           //IPV4,数据报套接字类型,不指定协议

    //说明本服务器地址
    const struct sockaddr_in srvaddr = {
        .sin_family = AF_INET,                              //协议类型IPV4
        .sin_port = htons(PORT),                            //端口号-网络字节序
        .sin_addr.s_addr = htonl(INADDR_ANY)                //IP地址-任意地址
    };

    //绑定地址
    bind(sock_fd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));

    //接收数据
    char buf[BUF_SIZE] = { 0 };
    struct sockaddr_in cliaddr;
    socklen_t cliaddrlen = sizeof(cliaddr);
    while (1)
    {
        bzero(buf, BUF_SIZE);
        bzero(&cliaddr, cliaddrlen);
        recvfrom(sock_fd, buf, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &cliaddrlen);
        printf("udp server from [%s - %hu]:%s\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port,buf);
    }

    //关闭套接字
    close(sock_fd);

    return 0;
}

2.运行结果

3.UDP单播服务器注意点

服务器之所以要bind是因为它的本地port需要是固定,而不是随机的,服务器也可以主动地给客户端发送数据。

四、UDP单播客户端代码实现

1.代码分析

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

#define BUF_SIZE 88
#define PROT     55555
#define ADDR     "192.168.111.213"

int main(int argc, char *argv[])
{
    //建立套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);           //IPV4,数据报套接字类型,不指定协议

    //声明将连接地址
    const struct sockaddr_in  srvaddr = {
        .sin_family = AF_INET,                              //协议类型IPV4
        .sin_port = htons(PROT),                            //端口号-网络字节序
        .sin_addr.s_addr = inet_addr(ADDR)                  //IP地址-字符串转IP
    };

    //发送数据
    char buf[BUF_SIZE] = { 0 };
	int count = 0;
    while (1)
    {
        memset(buf,0, BUF_SIZE);
        sprintf(buf, "%d",count);
		printf("udp client send:[%s - %d]:%s\n",ADDR,PROT,buf);
        sendto(sock_fd, buf, strlen(buf), 0, (const struct sockaddr*)&srvaddr, sizeof(srvaddr));
		count++;
		sleep(1);
    }

    //关闭套接字
    close(sock_fd);

    return 0;
}

2.运行结果

3.UDP单播客户端注意点

在客户端的代码中,我们只设置了目的IP、目的端口客户端的本地ip、本地port是我们调用sendto的时候linux系统底层自动给客户端分配的;分配端口的方式为随机分配,即每次运行系统给的port不一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProYuan28

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值