Linux网络编程(UDP套接字)

一、UDP协议

简介

UDP全称是用户数据报协议,是一种无连接的传输协议。相比于TCP它的优缺点:

优点:传输速度快、资源消耗小、编程简单,在音视频数据传输中常用。

缺点:网络质量不好时,丢包严重、会照成数据丢失、损毁。

通信流程

因为UDP是无连接的,所以通信流程会略有不同:

在这里插入图片描述

从图可以看出,使用UDP进行通信不需要双方建立连接就可以直接进行通信。

二、API函数

使用UDP进行网络编程,Linux另外提供了一些函数。

2.1 sendto发送

这个是在UDP模式下使用的数据发送函数,与TCP模式的区别就是每次发送都需要目标的地址等信息。

函数原型:

#include <sys/types.h>
#include <sys/socket.h>

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

参数说明:

  • sockfd:socket文件描述符。
  • buf:发送的内容。
  • len:发送数据的长度。
  • flags:标志,可以使用此参数设置不同数据传输方式,一般使用0。
  • dest_addr:目标地址信息,封装在socketaddr结构体中。
  • addrlen:目标地址信息大小。
  • 返回值:发送成功返回发送的字节数,失败返回-1,并设置相应的错误到errno。
2.2 recvfrom接收

函数原型:

#include <sys/types.h>
#include <sys/socket.h>

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

参数说明:

  • sockfd:socket文件描述符。
  • buf:数据缓冲区,用于存放接收的数据。
  • len:需要接收的数据长度。
  • flags:标志,可以使用此参数设置不同数据传输方式,一般使用0。
  • src_addr:源地址信息,封装在socketaddr结构体中。
  • addrlen:源地址信息大小,指针
  • 返回值:接收成功返回接收到的字节数,失败返回-1,并设置相应的错误到errno。

其他函数参看前面的博客:

三、UDP通信实例

client.c(先发送端):
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef struct sockaddr* saddrp;

int main(int argc, char const *argv[])
{
     int sockfd = socket(AF_INET,SOCK_DGRAM,0);
     if (0 > sockfd)
     {
          perror("socket");
          return -1;
     }
     struct sockaddr_in addr = {};
     addr.sin_family = AF_INET;
     addr.sin_port = htons(12345);
     addr.sin_addr.s_addr = inet_addr("127.0.0.1");

     socklen_t addr_len = sizeof(struct sockaddr_in);
     while(1)
     {
          char buf[255] = {};
          printf("Please input cData:");
          gets(buf);
          sendto(sockfd,buf,strlen(buf)+1,0,(saddrp)&addr,sizeof(addr));
          if(0 == strncmp(buf, "end", 3)) break;

          recvfrom(sockfd,buf,sizeof(buf),0,(saddrp)&addr,&addr_len);
          printf("cRecv:%s\n",buf);
          printf("the ipaddr = %#x\n", addr.sin_addr.s_addr);
          printf("the port = %d\n", addr.sin_port);
          if(0 == strncmp(buf, "end", 3)) break;

     }
     close(sockfd);
     return 0;
}
server.c(先接收端):
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>

typedef struct sockaddr* saddrp;

int main(int argc, char const *argv[])
{
     //创建socket
     int sockfd = socket(AF_INET,SOCK_DGRAM,0);
     if (0 > sockfd)
     {
          perror("sockfd");
          return -1;
     }
     //准备地址
     struct sockaddr_in addr = {};
     addr.sin_family = AF_INET;//ipv4
     addr.sin_port = htons(12345);//端口号
     addr.sin_addr.s_addr = htonl(INADDR_ANY);//自动获取ip
     //绑定
     int ret = bind(sockfd,(saddrp)&addr,sizeof(addr));
     if (0 > ret)
     {
          perror("bind");
          return -1;
     }
     struct sockaddr_in src_addr ={};
     socklen_t addr_len = sizeof(struct sockaddr_in);
     while(1)
     {
          char buf[255] = {};
          //接收数据和来源的ip地址
          recvfrom(sockfd,buf,sizeof(buf),0,(saddrp)&src_addr,&addr_len);
          printf("sRecv:%s\n",buf);
          if (0 == strncmp(buf,"end",3)) break;
          //发送数据给目标地址
          printf("Please input sData to send:");
          gets(buf);
          sendto(sockfd,buf,strlen(buf)+1,0,(saddrp)&src_addr,addr_len);
          if (0 == strncmp(buf,"end", 3)) break;
     }  
     //关闭socket对象
     close(sockfd);
     return 0;
}
运行结果:

client:
在这里插入图片描述

server:
在这里插入图片描述

分析:

客户端先发送数据给服务器,服务区获取到数据后知道客户端的地址信息,就可以向客户端发送数据了,一般都是客户端先发送,服务器先接收。输入end会两边都会判断进行结束。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值