Linux 网络编程——UDP编程

2023-05-16

一、概述

UDP 是 User Datagram Protocol 的简称, 中文名是用户数据报协议,是一个简单的面向数据报的运输层协议,在网络中用于处理数据包,是一种无连接的协议。UDP 不提供可靠性的传输,它只是把应用程序传给 IP 层的数据报发送出去,但是并不能保证它们能到达目的地。由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。


UDP 有如下的特点:

1)邮件系统服务模式的抽象(可通过邮件模型来进行对比)

2)每个分组都携带完整的目的地址

3)发送数据之前不需要建立链接

4)不对数据包的顺序进行检查,不能保证分组的先后顺序

5)不进行分组出错的恢复和重传

6)不保证数据传输的可靠性



在网络质量令人十分不满意的环境下,UDP 协议数据包丢失会比较严重。但是由于 UDP 的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的 ICQ 和 QQ 就是使用的 UDP 


二、UDP 编程的 C/S 

UDP 客户端程序

对比于写信模型,客户端相当于寄信人,要想成功给人寄信,信封上必须写上对方的地址。

ssize_t sendto(int sockfd,

const void *buf,

size_t nbytes,

int flags,

const struct sockaddr *to,        

socklen_t addrlen );

功能

向 to 结构体指针中指定的 ip,发送 UDP 数据,可以发送 0 长度的 UDP 数据包

参数

sockfd:套接字

buf:发送数据缓冲区

nbytes:发送数据缓冲区的大小

flags:一般为 0

to:指向目的主机地址结构体的指针

addrlen:to 所指向内容的长度

返回值

成功:发送数据的长度

失败: -1


这里通过 Windows 的网络调试助手和虚拟机中的 ubuntu 客户端程序进行通信,网络调试助手下载请点此处。


Windows 的网络调试助手作为服务器,接收客户端的请求,调试助手配置如下:



虚拟机中 ubuntu 的 UDP 客户端程序:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <unistd.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8.   
  9. int main(int argc, charchar *argv[])  
  10. {  
  11.     unsigned short port = 8080//服务器端口  
  12.     charchar *server_ip = "10.221.20.10";   //服务器ip地址  
  13.       
  14.     if( argc > 1 )   // main函数传参,服务器ip地址  
  15.     {     
  16.         server_ip = argv[1];  
  17.     }  
  18.       
  19.     if( argc > 2 )   // main函数传参,服务器端口  
  20.     {  
  21.         port = atoi(argv[2]);  
  22.     }  
  23.   
  24.     int sockfd;  
  25.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);   //创建UDP套接字  
  26.     if(sockfd < 0)  
  27.     {  
  28.         perror("socket");  
  29.         exit(-1);  
  30.     }  
  31.       
  32.     // 套接字地址  
  33.     struct sockaddr_in dest_addr;  
  34.     bzero(&dest_addr, sizeof(dest_addr));   // 清空内容  
  35.     dest_addr.sin_family = AF_INET;     // ipv4  
  36.     dest_addr.sin_port   = htons(port); // 端口转换  
  37.     inet_pton(AF_INET, server_ip, &dest_addr.sin_addr); // ip地址转换  
  38.   
  39.     printf("send data to UDP server %s:%d!\n", server_ip, port);  
  40.       
  41.     while(1)  
  42.     {  
  43.         char send_buf[512] = "";  
  44.         fgets(send_buf, sizeof(send_buf), stdin);//获取输入  
  45.         send_buf[strlen(send_buf)-1] = '\0';  
  46.         //发送数据  
  47.         int len = sendto(sockfd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr));  
  48.         printf("len = %d\n", len);  
  49.     }  
  50.       
  51.     close(sockfd);  
  52.     return 0;  
  53. }  


运行结果如下:


UDP 客户端注意点

1)本地IP、本地端口(我是谁)

2)目的IP、目的端口(发给谁)

3)在客户端的代码中,我们只设置了目的IP、目的端口

4)客户端的本地 ip、本地 port 是我们调用 sendto 的时候 linux 系统底层自动给客户端分配的;分配端口的方式为随机分配,即每次运行系统给的 port 不


三、UDP 服务器程序

UDP网络程序想要收取数据需什么条件?

1)确定的 ip 地址

2)确定的端口(port)

这正如,我要收到别人寄过来的信,我必须告诉别人我的地址(ip),同时告诉别人我我的公寓信箱号(端口)。


接收端使用 bind() 函数,来完成地址结构与 socket 套接字的绑定,这样 ip、port 就固定了,发送端在 sendto 函数中指定接收端的 ip、port,就可以发送数据了。


需要头文件:#include <sys/socket.h>

int bind(    int sockfd,

const struct sockaddr *myaddr,

socklen_t addrlen );

功能

将本地协议地址与 sockfd 绑定,这样 ip、port 就固定了

参数

sockfd: socket 套接字

myaddr: 指向特定协议的地址结构指针

addrlen:该地址结构的长度

返回值

成功:返回 0

失败:-1


使用实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // 本地网络地址  
  2. struct sockaddr_in my_addr;  
  3. bzero(&my_addr, sizeof(my_addr));   // 清空结构体内容  
  4. my_addr.sin_family = AF_INET;   // ipv4  
  5. my_addr.sin_port   = htons(port);   // 端口转换  
  6. my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定网卡所有ip地址,INADDR_ANY为通配地址,值为0  
  7.   
  8. printf("Binding server to port %d\n", port);  
  9. int err_log;  
  10. err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); // 绑定  
  11. if(err_log != 0)  
  12. {  
  13.     perror("bind");  
  14.     close(sockfd);        
  15.     exit(-1);  
  16. }  

绑定端口有些需要注意的问题,请看《绑定( bind )端口需要注意的问题》。


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 所指内容的长度

返回值

成功:接收到的长度

失败: -1


ubuntu 中的服务器程序如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include <unistd.h>  
  5. #include <sys/socket.h>  
  6. #include <netinet/in.h>  
  7. #include <arpa/inet.h>  
  8. int main(int argc, charchar *argv[])  
  9. {  
  10.     unsigned short port = 8000;     // 本地端口  
  11.     if(argc > 1)  
  12.     {  
  13.         port = atoi(argv[1]);  
  14.     }  
  15.   
  16.     int sockfd;  
  17.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);    // 创建套接字  
  18.     if(sockfd < 0)  
  19.     {  
  20.         perror("socket");  
  21.         exit(-1);  
  22.     }  
  23.       
  24.     // 本地网络地址  
  25.     struct sockaddr_in my_addr;  
  26.     bzero(&my_addr, sizeof(my_addr));   // 清空结构体内容  
  27.     my_addr.sin_family = AF_INET;   // ipv4  
  28.     my_addr.sin_port   = htons(port);   // 端口转换  
  29.     my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定网卡所有ip地址,INADDR_ANY为通配地址,值为0  
  30.       
  31.     printf("Binding server to port %d\n", port);  
  32.     int err_log;  
  33.     err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); // 绑定  
  34.     if(err_log != 0)  
  35.     {  
  36.         perror("bind");  
  37.         close(sockfd);        
  38.         exit(-1);  
  39.     }  
  40.       
  41.     printf("receive data...\n");  
  42.     while(1)  
  43.     {  
  44.         int recv_len;  
  45.         char recv_buf[512] = "";  
  46.         struct sockaddr_in client_addr;  
  47.         char cli_ip[INET_ADDRSTRLEN] = "";//INET_ADDRSTRLEN=16  
  48.         socklen_t cliaddr_len = sizeof(client_addr);   
  49.           
  50.         // 接受数据  
  51.         recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);  
  52.         inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
  53.         printf("\nip:%s ,port:%d\n",cli_ip, ntohs(client_addr.sin_port));  
  54.         printf("data(%d):%s\n",recv_len,recv_buf);  
  55.     }  
  56.       
  57.     close(sockfd);  
  58.     return 0;  
  59. }  

Windows 的网络调试助手作为客户端,给 ubuntu 中的服务器发送数据,调试助手配置如下:



运行结果如下:



示例代码下载请点此处。

转自:http://blog.csdn.net/tennysonsky/article/details/45047133

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 网络编程——UDP编程 的相关文章

  • 下一代CAN通信技术CAN XL简介

    众所周知 xff0c CAN网络具有易于实现 可扩展 并支持复杂拓扑结构等诸多优点 xff0c 所以目前在各个行业特别是汽车领域 xff0c 得到了非常广泛的应用 但是 xff0c 它也存在着诸多问题 xff0c 其中最大的一点就是总线带宽
  • 聊一下质量管理体系中的DQE/SQE/PQE/CQE

    最近接触了不少质量体系的话题 xff0c 反复的听到SQE DQE等 xff0c 大概知道是跟质量管理相关的一些职位 xff0c 但是具体也不是很清楚 xff0c 于是干脆来理一下 正式开始之前 xff0c 先要介绍一下他们的老祖宗 xff
  • C语言字符串库函数 #include <string.h>

    c语言字符串库函数 include lt string h gt 在头文件 lt string h gt 中定义了两组字符串函数 第一组函数的名字以str开头 xff1b 第二组函数的名字以mem开头 只有函数memmove对重叠对象间的拷
  • gcc编译动态库静态库及Makefile知识汇总;

    gcc编译 动态库静态库及Makefile知识汇总 gcc编译过程gcc的常用选项静态库 xff0c 动态库并制作 xff1b Makefile 基本使用make工具简介 gcc编译过程 我们在Linux下使用vim命令写的 c文件 xff
  • 简单学习一下Linux中的环境变量

    环境变量 最近在学习Linux下的C程序编写 xff0c 在运行可执行程序的时候有个问题就是链接的问题 xff0c 最后通过学习才知道是因为环境变量没有设置好 xff1b 环境变量在进行linux开发过程中经常碰到 xff0c 那什么是环境
  • STM32-ESP8266wifi模块实现

    1 ESP8266WiFi模块介绍 1 1ESP8266wifi 模块 低功耗串口WiFi模块ESP8266内置一个Tensilica xff08 泰思立达 xff09 Xtensa架构的32位处理器L106 xff0c 具有5级流水线 A
  • ESP8266WiFi模块实现代码

    ESP8266WiFi模块实现TCP连接服务器 在前面的博客里 xff08 STM32 ESP8266wifi模块实现 xff09 说到了通过AT命令配置ESP8266实现TCP连接 他的流程是 xff0c 1 xff0c 使能串口 xff
  • 2021-05-14 Redis面试题 redis 部署生产环境

    redis 部署生产环境 redis cluster xff0c 10 台机器 xff0c 5 台机器部署了 redis 主实例 xff0c 另外 5 台机器部署了 redis 的从实例 xff0c 每个主实例挂了一个从实例 xff0c 5
  • 实现Basic认证

    Basic认证是一种较为简单的HTTP认证方式 xff0c 客户端通过明文 xff08 Base64编码格式 xff09 传输用户名和密码到服务端进行认证 xff0c 通常需要配合HTTPS来保证信息传输的安全 Maven依赖 lt par
  • STM32的串口空闲中断

    STM32串口使用DMA方式接收数据可以减小CPU的开销 对于接收定长数据 xff0c 可以将DMA接收缓冲区的长度设定为待接收数据的长度 xff0c 这样利用DMA的传输完成中断DMAx IT TCy就可以知道已经接收了一帧数据 对于接收
  • C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)

    C code namespace UDPServer class Program static void Main string args int recv byte data 61 new byte 1024 构建TCP 服务器 得到本机
  • http digest认证(Java server)

    背景 xff1a 服务器接收客户端请求 xff0c 处理并验证 并返回服务器的验证结果 关于digest认证的相关概念及验证原理查看相关的说明 xff0c 此处只对处理进行贴码 CODE import com alibaba fastjso
  • 测试apache时出现[error] [client 192.168.6.1] File does not exist: /etc/httpd/htdocs

    问题 xff1a 测试apache时出现 error client 192 168 6 1 File does not exist etc httpd htdocs 解决方法 xff1a 1 创建文件夹htdocs xff08 etc ht
  • HAL库 STM32 串口通信函数

    HAL UART Receive IT串口 xff01 HAL UART Receive IT amp UART1 Handler u8 aRxBuffer RXBUFFERSIZE HAL UART Receive IT函数使用的时候 简
  • linux环境下安装QT超详细

    QT安装 1 首先下载QT安装包 QT官网 xff1a Index of archive qt 我这里使用的是qt opensource linux x64 5 14 0 run版本 2 打开终端 xff0c 输入命令 xff0c 赋予安装
  • 使用ssh连接虚拟机保姆级教程

    首先安装SSH 安装先检测是否已经安装SSH xff1a service ssh status 如果出现提示 xff1a ssh unrecognized service 说明没有安装openSSH xff0c 则需安装ssh SSH 服务
  • 小游戏2048设计思路超简单

    2048作为一个经典的小游戏 xff0c 对于C语言的逻辑练习是一个比较好的案例了 xff0c 看似很复杂 xff0c 但是如果掌握了设计思路 xff0c 那么就不会觉得难了 xff0c 而且会了这个之后对今后编程的也会有很大的帮助 先分析
  • ES-Elasticsearch查看所有索引及查看某索引下的信息

    1 查看所有索引 xff0c 地址栏直接访问下面的连接 http localhost 9200 cat indicesv amp pretty 2 查看某索引下存的信息 xff0c 查询的信息为索引结构信息 xff08 indexName为
  • 教你十分钟搭建博客,已在多台电脑测试,无坑

    1 前期工作 1 注册Github账号 官网地址 xff1a GitHub 2 下载安装git Git软件下载地址 xff1a Git Downloading Package git scm com 安装的话一直点next就可以了 3 绑定
  • MQTT使用TLS加密

    使用TLS加密在MQTT的使用中是比较常见的 xff0c TLS加密过程在网上有很多说明 xff0c 但是没几个应用教程的 xff0c MQTT软件中的EMQX软件是支持TLS加密的 xff0c 只不过要进行一些设置 安装EMQX软件 首先

随机推荐

  • linux下将QT移植至arm环境

    前言 讲下整个项目流程 xff0c 我们的目标是把qt编出来程序放在arm开发板上面跑 xff0c 首先下载QT源码和tslib源码 xff08 QT源码编译和QT程序运行需要tslib库的支持 xff09 xff0c 在虚拟机里使用交叉编
  • linux下移植onvif至arm环境

    前言 onvif是一种网络摄像头协议 xff0c linux网络摄像头这一块是需要移植onvif协议的 xff0c 整个移植过程是这样的 xff0c 首先onvif协议是依赖于gsoap的 xff0c 所以需要先将gsoap编译安装 xff
  • C语言使用二级指针实现字符串分割

    话不多说 xff0c 直接上代码 include lt stdio h gt int opt char p char ch char res char q 61 p if q 61 61 NULL q 61 61 39 0 39 retur
  • 已include包却提示未定义标识符

    已 include lt string gt xff0c include lt vector gt 却提示string xff0c vector未定义的标识符 因为没定义默认的命名空间 xff0c 改为std string xff0c st
  • jpg和png的区别小结

    png图像的大小是jpg图像大小的数倍 xff0c png为可移植网络图形格式 xff0c 也是一种位图文件存储格式 xff0c 可以进行无损压缩 xff0c jpg是最常见的图像格式 xff0c 图像占用的存储较小 xff0c 但是牺牲了
  • 色彩空间中的HSL、HSV、HSB有什么区别?

    作者 xff1a 大蔚陈 链接 xff1a https www zhihu com question 22077462 answer 29483467 来源 xff1a 知乎 著作权归作者所有 商业转载请联系作者获得授权 xff0c 非商业
  • opencv小程序练习——createBackgroundSubtractorMOG2()实现跟踪

    思想 xff1a 使用createBackgroundSubtractorMOG2 使用运动物体背景分割 使用findContours 查找轮廓并画出 实现一定感官上的跟踪功能 代码如下 xff1a include lt opencv2 o
  • opencv_tutorial_code学习——canny边缘检测后findContours

    tutorial code ShapeDescriptors findContours demo cpp 步骤 xff1a 1 灰度化 2 滤波 3 canny边缘检测 4 findContours canny output contour
  • idea开发工具右侧没有maven工具栏

    一 解决方式一 依次点击 View gt Tool Windows gt Maven xff0c 如下图 xff1a 二 解决方式二 点击如图所示IDEA界面最左下角的按钮 xff0c 如下图 xff1a 三 解决方式三 1 打开项目的 p
  • 语义分割与实例分割的区别

    目前的分割任务主要有两种 xff1a xff08 1 xff09 像素级别的语义分割 xff08 2 xff09 实例分割 这个有意思 xff0c 什么叫实例分割呢 xff1f 它与语义分割有什么区别与联系呢 xff1f 顾名思义 xff0
  • tiny-dnn配置运行

    tiny dnn是一个轻量级的CNN xff08 卷积神经网络 xff09 xff0c 不需要各种依赖和GPU xff0c 由三千多行C 43 43 代码完成 适配android平台的话 xff0c 感觉这个比较好做一点 下载地址 xff1
  • SSM笔记

    进入数据库 xff1a 34 D Program Files x86 mysql 5 7 20 winx64 bin mysql exe 34 u root p admin 展示数据库 xff1a show databases 创建数据库
  • 工程编译那点事:Makefile和cmake(一)

    makefile 前言Makefile介绍 Makefile规则make是如何工作的Makefile使用变量让make自动推导另类风格的Makefilemake中的函数文件搜索绝对顶级的大型工程Makefile 前言 一个项目 xff0c
  • 头文件相互包含问题

    先来看看以下这个例子 xff1a Keyboard h的代码为 span class token macro property span class token directive hash span span class token di
  • 解决roslaunch启动stage_ros节点仿真时输出rostopic hz速率较低的问题(始终为10Hz)

    问题描述 xff1a 在实验过程中偶然间发现无论是odom还是laser scan的输出频率都只有10Hz clock输出速率有50Hz 直接使用命令 rosrun stage ros stageros test world能够正常输出50
  • STM32八种IO口模式区别

    xff08 1 xff09 GPIO Mode AIN 模拟输入 xff08 2 xff09 GPIO Mode IN FLOATING 浮空输入 xff08 3 xff09 GPIO Mode IPD 下拉输入 xff08 4 xff09
  • linux下C++实现Http请求类(GET,POST,上传,下载)

    linux下C 43 43 实现Http请求类 GET xff0c POST xff0c 上传 xff0c 下载 Http协议简述 协议 xff1a 网络协议的简称 xff0c 网络协议是通信计算机双方必须共同遵从的一组约定 如怎么样建立连
  • 正点原子MiniFly V1.2学习笔记四---txQueue队列数据哪来

    笔记二的第四点中 xff0c 把解包出来的指令发送到 rxQueue队列里 xff0c 然后从txQueue队列取数据发送到串口 那么txQueue队列的数据从哪里来的 一 txQueue数据从哪里来 xff1f 二 什么地方会调用radi
  • redis链接工具

    redis链接工具 今天推荐一款redis链接工具 xff0c 其实世面上连接redis的工具很多 xff0c 但是好用的很少 例如 xff1a redis desktop manager这款工具也不错 xff0c 但是我个人不能使用 xf
  • Linux 网络编程——UDP编程

    一 概述 UDP 是 User Datagram Protocol 的简称 xff0c 中文名是用户数据报协议 xff0c 是一个简单的面向数据报的运输层协议 xff0c 在网络中用于处理数据包 xff0c 是一种无连接的协议 UDP 不提