0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux下网络编程-UDP协议探测在线好友

DS小龙哥-嵌入式技术 来源:DS小龙哥-嵌入式技术 作者:DS小龙哥-嵌入式技 2022-08-14 09:23 次阅读

1. UDP协议介绍

UDP协议 相对TCP协议来讲属于不可靠协议,UDP协议是广播方式发送数据,没有服务器和客户端的概念。

Linux下使用socket创建UDP的套接字时,属性要选择数据报类型SOCK_DGRAM

 sockfd=socket(AF_INET,SOCK_DGRAM,0);
复制代码

2. UDP协议发送和接收数据的函数

2.1 recvfrom函数

UDP使用recvfrom()函数接收数据,他类似于标准的read(),但是在recvfrom()函数中要指明数据的目的地址。

#include  
#include  
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * from, size_t *addrlen);
复制代码

返回值

成功返回接收到数据的长度,负数失败

前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。最后两个参数类似于accept的最后两个参数(接收客户端的IP地址)。

2.2 sendto函数

UDP使用sendto()函数发送数据,他类似于标准的write(),但是在sendto()函数中要指明目的地址。

#include  
#include  
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * to, int addrlen);
复制代码

返回值

成功返回发送数据的长度,失败返回-1

前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。

参数to指明数据将发往的协议地址,他的大小由addrlen参数来指定。

2.3 设置套接字属性

#include      /* See NOTES */
#include 
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
复制代码

setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。

参数介绍:

sockfd:标识一个套接口的描述字。
level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
optname:需设置的选项。
optval:指针,指向存放选项值的缓冲区。
optlen:optval缓冲区的长度。
UDP协议发送数据时,设置具有广播特性: 默认情况下socket不支持广播特性
char bBroadcast=1;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(char));
复制代码

3.案例: UDP协议完成数据收发

3.1 接收数据示例

#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/* According to POSIX.1-2001 */
#include 

int main(int argc,char **argv)
{
    if(argc!=2)
    {
        printf("参数: ./tcp_server <端口号>\n");
        return 0;
    }

     /*1. 创建socket套接字*/
    int sockfd;
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        printf("服务器:套接字创建失败.\n");
        return 0;
    }
    /*2. 绑定端口号*/
    struct sockaddr_in addr;
    addr.sin_family=AF_INET; //IPV4
    addr.sin_port=htons(atoi(argv[1])); //65535
    //addr.sin_addr.s_addr=inet_addr("192.168.2.16");
    addr.sin_addr.s_addr=INADDR_ANY; //本地所有IP地址 "0.0.0.0"
    if(bind(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr)))
    {
        printf("服务器:端口号绑定失败.\n");
        return 0;
    }
    /*3. 接收数据*/
    char buff[100];
    struct sockaddr_in from;
    size_t addrlen=sizeof(struct sockaddr);
    ssize_t len;
    while(1)
    {
        //带阻塞功能,收到数据才会返回
        len=recvfrom(sockfd,buff,sizeof(buff)-1,0,(struct sockaddr*)&from,&addrlen);
        buff[len]='\0';
        printf("接收到数据:%s,长度=%d,数据来自于:%s:%d\n",buff,len,inet_ntoa(from.sin_addr),ntohs(from.sin_port));
    }
}
复制代码

3.2 发送数据示例

#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/* According to POSIX.1-2001 */
#include 
#include 

int main(int argc,char **argv)
{
     if(argc!=4)
    {
        printf("参数: ./tcp_client  <端口号> <发送的数据>\n");
        return 0;
    }

    /*1. 创建socket套接字*/
    int sockfd;
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        printf("服务器:套接字创建失败.\n");
        return 0;
    }

    const int opt = 1;
    //设置该套接字为广播类型,
    int nb = 0;
    nb = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
    if(nb == -1)
    {
        printf("设置广播类型错误.\n");
    }

    /*2. 开始发送数据*/
    struct sockaddr_in addr;
    addr.sin_family=AF_INET; //IPV4
    addr.sin_port=htons(atoi(argv[2])); //65535  服务器的端口号
    addr.sin_addr.s_addr=inet_addr(argv[1]); //服务器IP地址

    ssize_t len;
    while(1)
    {
        len=sendto(sockfd,argv[3],strlen(argv[3]),0,(const struct sockaddr*)&addr,sizeof(struct sockaddr));
        printf("成功发送:%d\n",len);
        sleep(1);
    }
}
复制代码地址>

4. 案例: 使用UDP协议探测在线好友

前面几篇文章介绍了Linux下TCP协议设计的群聊天室的一个程序,如果想要知道同一个网络下有多少好友在线,就可以使用UDP协议进行广播探测。 大家的端口号是固定的,也就是只要在这个网络范围内,大家都跑这个同一个聊天室程序,就可以互相探测,得到对方IP地址之后,再完成TCP协议建立,完成点对点聊天通信

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
​
​
#define SEND_MSG "1314520"  //发送的数据包
#define PORT 8888      //固定的端口号
​
int sockfd;
int main(int argc,char **argv)
{  
  if(argc!=2)
   {
    printf("./app <广播地址>  当前程序固定的端口号是8888\n");
    return 0;
   }

  /*1. 创建socket套接字*/
  sockfd=socket(AF_INET,SOCK_DGRAM,0);

  //设置端口号的复用功能
  int on = 1;
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

  /*2. 绑定端口号与IP地址*/
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(PORT); // 端口号0~65535
  addr.sin_addr.s_addr=INADDR_ANY;  //inet_addr("0.0.0.0"); //IP地址
  if(bind(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr))!=0)
   {
    printf("UDP服务器:端口号绑定失败.\n");
    return 0;
   }
  /*3. 接收数据*/
  unsigned char buff[1024+1];
  int cnt;
  struct sockaddr_in client_addr;
  socklen_t addrlen=sizeof(struct sockaddr_in);

  struct pollfd fds;
  fds.fd=sockfd;
  fds.events=POLLIN;
  while(1)
   {
    cnt=poll(&fds,1,1000);
    if(cnt>0)
     {
      cnt=recvfrom(sockfd,buff,1024,0,(struct sockaddr *)&client_addr,&addrlen);
      buff[cnt]='\0';
      
      //判断是不是探测包数据
      if(strcmp(buff,SEND_MSG)==0)
       {
        printf("在线好友:%s,%d-->%s:%d\n",buff,cnt,inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
        cnt=sendto(sockfd,SEND_MSG,strlen(SEND_MSG),0,(const struct sockaddr *)&client_addr,sizeof(struct sockaddr));
        printf("回应探测包:%d字节.\n",cnt);
​
        //这里可以继续写代码,将存在的好友保存在链表,并记录在线好友数量
       }
     }
    else
     {
      ssize_t cnt;
      struct sockaddr_in addr;
      addr.sin_family=AF_INET;
      addr.sin_port=htons(PORT); // 端口号0~65535
      addr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址
​
      cnt=sendto(sockfd,SEND_MSG,strlen(SEND_MSG),0,(const struct sockaddr *)&addr,sizeof(struct sockaddr));
      printf("探测包发送:%d字节.\n",cnt);
     }
   }
  return 0;
}

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11276

    浏览量

    209263
  • UDP
    UDP
    +关注

    关注

    0

    文章

    325

    浏览量

    33929
  • 网络编码
    +关注

    关注

    0

    文章

    38

    浏览量

    11599
收藏 人收藏

    评论

    相关推荐

    UDP网络编程

    UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输
    的头像 发表于 08-26 20:58 1411次阅读
    <b class='flag-5'>UDP</b><b class='flag-5'>网络</b><b class='flag-5'>编程</b>

    基于UDP协议网络通信应用程序

    基于UDP协议网络通信应用程序(UDP-Socket)前两篇文章介绍了基于TCP/IP协议网络
    发表于 11-05 08:29

    基于UDP协议的Socket网络编程模式的实现

    传输层进行网络通信编程的接口是Socket&它是通用的开发网络通信程序标准) 本文介绍了基于UDP协议Socket
    发表于 09-09 15:10 42次下载

    Linux下的UDP协议编程

    Linux下的UDP协议编程 介绍UDP协议,并提供一个适用于客户端和服务器端的实例子程序。 
    发表于 10-16 22:22 3973次阅读
    <b class='flag-5'>Linux</b>下的<b class='flag-5'>UDP</b><b class='flag-5'>协议</b><b class='flag-5'>编程</b>

    UDP协议,UDP协议是什么意思

    UDP协议,UDP协议是什么意思 UDP 是User Datagram Protocol的简称, 中文名是用户数据包
    发表于 03-29 17:35 1488次阅读

    linux下网卡配置详解

    linux下网卡配置详解
    发表于 12-15 22:38 0次下载

    udp协议详细介绍与qudpsocket编程

    关于udp协议详细介绍与qudpsocket编程UDP报头由4个域组成,其中每个域各占用2个字节,具体如下: 端口号 ,目标端口号 ,数据报长度 ,校验值
    发表于 12-08 14:57 9260次阅读
    <b class='flag-5'>udp</b><b class='flag-5'>协议</b>详细介绍与qudpsocket<b class='flag-5'>编程</b>

    Linux下网络怎样来配置总结

    Linux下网络配置总结
    发表于 11-07 11:35 897次阅读

    Linux下网络编程TCP并发服务器和TCP客户端程序免费下载

    本文档的主要内容详细介绍的是Linux下网络编程TCP并发服务器和TCP客户端程序免费下载
    发表于 01-08 15:12 9次下载
    <b class='flag-5'>Linux</b><b class='flag-5'>下网络</b><b class='flag-5'>编程</b>TCP并发服务器和TCP客户端程序免费下载

    tcp和udp协议的异同

    UDP 校验和则是包含 UDP 首部和数据在内的校验结果。 TCP协议 TCP协议基于网络层的 IP
    的头像 发表于 11-12 14:45 4054次阅读
    tcp和<b class='flag-5'>udp</b><b class='flag-5'>协议</b>的异同

    嵌入式Linux应用程序开发-(9)UDP网络通信应用程序(UDP-Socket)

    基于UDP协议网络通信应用程序(UDP-Socket)前两篇文章介绍了基于TCP/IP协议网络
    发表于 11-02 12:21 35次下载
    嵌入式<b class='flag-5'>Linux</b>应用程序开发-(9)<b class='flag-5'>UDP</b><b class='flag-5'>网络</b>通信应用程序(<b class='flag-5'>UDP</b>-Socket)

    Linux应用开发【第六章】网络编程应用开发

    文章目录 6 网络编程应用开发 6.1 网络编程简介 6.1.1 五层因特网协议栈 6.1.2 传输层和应用层的常见
    的头像 发表于 12-10 19:17 542次阅读
    <b class='flag-5'>Linux</b>应用开发【第六章】<b class='flag-5'>网络</b><b class='flag-5'>编程</b>应用开发

    Linux编程UDP SOCKET攻略详解

    一、基本的udp socket编程 1. UDP编程框架 要使用UDP协议进行程序开发,我们必须
    的头像 发表于 05-21 16:23 2193次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>编程</b>之<b class='flag-5'>UDP</b> SOCKET攻略详解

    Linux下网络编程

    TCP/IP协议源于1969年,是针对Internet开发的一种体系结构和协议标准,目的在于解决异种计算机网络的通信问题。使得网络在互联时能为用户提供一种通用、一致的通信服务。是Int
    的头像 发表于 08-26 20:53 1137次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>下网络</b><b class='flag-5'>编程</b>

    Linux开发_网络编程网络通信介绍

    介绍Linux网络编程: TCP网络编程UDP网络
    的头像 发表于 09-17 15:46 1274次阅读
    <b class='flag-5'>Linux</b>开发_<b class='flag-5'>网络</b><b class='flag-5'>编程</b>、<b class='flag-5'>网络</b>通信介绍