(十四)UDP协议的两个主要方法sendto和recvfrom详解
在网络编程中,UDP运用非常广泛。很多网络协议是基于UDP来实现的,如SNMP等。大家常常用到的局域网文件传输软件飞鸽传书也是基于UDP实现的。
本篇文章跟大家分享linux下UDP的使用和实现,主要介绍下sendto()和recvfrom()两个函数的使用,以及INADDR_ANY的说明,并在最后展示了一个经过自己测试可用的UDP Server和UDP Client的代码示例。
关于UDP数据报
UDP都是以数据报的形式进行发送和接收的,而TCP是以数据流的形式进行发送和接收的。数据报和数据流,这两者要区分开来。
头文件
函数原型
int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
函数说明
sendto(),是把UDP数据报发给指定地址;recvfrom()是从指定地址接收UDP数据报。
参数说明
- \s: socket描述符。
- \buf: UDP数据报缓存地址。
- \len: UDP数据报长度。
- \flags: 该参数一般为0。
- \to: sendto()函数参数,struct sockaddr_in类型,指明UDP数据发往哪里报。
- \tolen: 对方地址长度,一般为:sizeof(struct sockaddr_in)。
- \from: recvfrom()函数参数,struct sockaddr 类型,指明UDP数据从哪里收。
- \fromlen:recvfrom()函数参数,struct sockaddr_in类型,指明从哪里接收UDP数据报。
函数返回值
对于sendto()函数,成功则返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。
对于recvfrom()函数,成功则返回接收到的字符数,失败则返回-1,错误原因存于errno中。
UDP Server和Client源码实例
UDP Server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#defineUDP_TEST_PORT50001
int main(int argC, char* arg[])
{
struct sockaddr_in addr;
int sockfd, len = 0;
int addr_len = sizeof(struct sockaddr_in);
char buffer[256];
/* 建立socket,注意必须是SOCK_DGRAM */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror ("socket");
exit(1);
}
/* 填写sockaddr_in 结构 */
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(UDP_TEST_PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY) ;// 接收任意IP发来的数据
/* 绑定socket */
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0) {
perror("connect");
exit(1);
}
while(1) {
bzero(buffer, sizeof(buffer));
len = recvfrom(sockfd, buffer, sizeof(buffer), 0,
(struct sockaddr *)&addr ,&addr_len);
/* 显示client端的网络地址和收到的字符串消息 */
printf("Received a string from client %s, string is: %s\n",
inet_ntoa(addr.sin_addr), buffer);
/* 将收到的字符串消息返回给client端 */
sendto(sockfd,buffer, len, 0, (struct sockaddr *)&addr, addr_len);
}
return 0;
}
// ----------------------------------------------------------------------------
// End of udp_server.c
UDP Client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#defineUDP_TEST_PORT50001
#define UDP_SERVER_IP "127.0.0.1"
int main(int argC, char* arg[])
{
struct sockaddr_in addr;
int sockfd, len = 0;
int addr_len = sizeof(struct sockaddr_in);
char buffer[256];
/* 建立socket,注意必须是SOCK_DGRAM */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(1);
}
/* 填写sockaddr_in*/
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(UDP_TEST_PORT);
addr.sin_addr.s_addr = inet_addr(UDP_SERVER_IP);
while(1) {
bzero(buffer, sizeof(buffer));
printf("Please enter a string to send to server: \n");
/* 从标准输入设备取得字符串*/
len = read(STDIN_FILENO, buffer, sizeof(buffer));
/* 将字符串传送给server端*/
sendto(sockfd, buffer, len, 0, (struct sockaddr *)&addr, addr_len);
/* 接收server端返回的字符串*/
len = recvfrom(sockfd, buffer, sizeof(buffer), 0,
(struct sockaddr *)&addr, &addr_len);
printf("Receive from server: %s\n", buffer);
}
return 0;
}
// ----------------------------------------------------------------------------
// End of udp_client.c
UDP Server:
01 |
#include <sys/types.h> |
02 |
#include <sys/socket.h> |
03 |
#include <netinet/in.h> |
04 |
#include <arpa/inet.h> |
05 |
#include <unistd.h> |
06 |
#include <stdlib.h> |
07 |
#include <string.h> |
08 |
#include <stdio.h> |
09 |
10 |
#define UDP_TEST_PORT 50001 |
11 |
12 |
int main(int argC, char* arg[]) |
13 |
{ |
14 |
struct sockaddr_in addr; |
15 |
int sockfd, len = 0; |
16 |
int addr_len = sizeof(struct sockaddr_in); |
17 |
char buffer[256]; |
18 |
19 |
/* 建立socket,注意必须是SOCK_DGRAM */ |
20 |
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
21 |
perror ("socket"); |
22 |
exit(1); |
23 |
} |
24 |
25 |
/* 填写sockaddr_in 结构 */ |
26 |
bzero(&addr, sizeof(addr)); |
27 |
addr.sin_family = AF_INET; |
28 |
addr.sin_port = htons(UDP_TEST_PORT); |
29 |
addr.sin_addr.s_addr = htonl(INADDR_ANY) ;// 接收任意IP发来的数据 |
30 |
31 |
/* 绑定socket */ |
32 |
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0) { |
33 |
perror("connect"); |
34 |
exit(1); |
35 |
} |
36 |
37 |
while(1) { |
38 |
bzero(buffer, sizeof(buffer)); |
39 |
len = recvfrom(sockfd, buffer, sizeof(buffer), 0, |
40 |
(struct sockaddr *)&addr ,&addr_len); |
41 |
/* 显示client端的网络地址和收到的字符串消息 */ |
42 |
printf("Received a string from client %s, string is: %s\n", |
43 |
inet_ntoa(addr.sin_addr), buffer); |
44 |
/* 将收到的字符串消息返回给client端 */ |
45 |
sendto(sockfd,buffer, len, 0, (struct sockaddr *)&addr, addr_len); |
46 |
} |
47 |
48 |
return 0; |
49 |
} |
50 |
51 |
// ---------------------------------------------------------------------------- |
52 |
// End of udp_server.c |
UDP Client:
01 |
#include <sys/types.h> |
02 |
#include <sys/socket.h> |
03 |
#include <netinet/in.h> |
04 |
#include <arpa/inet.h> |
05 |
#include <unistd.h> |
06 |
#include <stdlib.h> |
07 |
#include <string.h> |
08 |
#include <stdio.h> |
09 |
10 |
#define UDP_TEST_PORT 50001 |
11 |
#define UDP_SERVER_IP "127.0.0.1" |
12 |
13 |
int main(int argC, char* arg[]) |
14 |
{ |
15 |
struct sockaddr_in addr; |
16 |
int sockfd, len = 0; |
17 |
int addr_len = sizeof(struct sockaddr_in); |
18 |
char buffer[256]; |
19 |
20 |
/* 建立socket,注意必须是SOCK_DGRAM */ |
21 |
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
22 |
perror("socket"); |
23 |
exit(1); |
24 |
} |
25 |
26 |
/* 填写sockaddr_in*/ |
27 |
bzero(&addr, sizeof(addr)); |
28 |
addr.sin_family = AF_INET; |
29 |
addr.sin_port = htons(UDP_TEST_PORT); |
30 |
addr.sin_addr.s_addr = inet_addr(UDP_SERVER_IP); |
31 |
32 |
while(1) { |
33 |
bzero(buffer, sizeof(buffer)); |
34 |
35 |
printf("Please enter a string to send to server: \n"); |
36 |
37 |
/* 从标准输入设备取得字符串*/ |
38 |
len = read(STDIN_FILENO, buffer, sizeof(buffer)); |
39 |
40 |
/* 将字符串传送给server端*/ |
41 |
sendto(sockfd, buffer, len, 0, (struct sockaddr *)&addr, addr_len); |
42 |
43 |
/* 接收server端返回的字符串*/ |
44 |
len = recvfrom(sockfd, buffer, sizeof(buffer), 0, |
45 |
(struct sockaddr *)&addr, &addr_len); |
46 |
printf("Receive from server: %s\n", buffer); |
47 |
} |
48 |
49 |
return 0; |
50 |
} |
51 |
52 |
// ---------------------------------------------------------------------------- |
53 |
// End of udp_client.c |
上述代码是经过验证可用的。
(十四)UDP协议的两个主要方法sendto和recvfrom详解的更多相关文章
- 《手把手教你》系列基础篇(八十四)-java+ selenium自动化测试-框架设计基础-TestNG日志-上篇(详解教程)
1.简介 TestNG还为我们提供了测试的记录功能-日志.例如,在运行测试用例期间,用户希望在控制台中记录一些信息.信息可以是任何细节取决于目的.牢记我们正在使用Selenium进行测试,我们需要有助 ...
- 三十四 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解
信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行一个函数 dispatcher.connect()信号分发器,第一个参数信号触发函数,第二 ...
- 《手把手教你》系列技巧篇(四十五)-java+ selenium自动化测试-web页面定位toast-上篇(详解教程)
1.简介 在使用appium写app自动化的时候介绍toast的相关元素的定位,在Web UI测试过程中,也经常遇到一些toast,那么这个toast我们这边如何进行测试呢?今天宏哥就分两篇介绍一下. ...
- 《手把手教你》系列技巧篇(四十六)-java+ selenium自动化测试-web页面定位toast-下篇(详解教程)
1.简介 终于经过宏哥的不懈努力,偶然发现了一个toast的web页面,所以直接就用这个页面来夯实一下,上一篇学过的知识-处理toast元素. 2.安居客 事先声明啊,宏哥没有收他们的广告费啊,纯粹是 ...
- [转帖]IP /TCP协议及握手过程和数据包格式中级详解
IP /TCP协议及握手过程和数据包格式中级详解 https://www.toutiao.com/a6665292902458982926/ 写的挺好的 其实 一直没闹明白 网络好 广播地址 还有 网 ...
- Mybatis系列全解(四):全网最全!Mybatis配置文件XML全貌详解
封面:洛小汐 作者:潘潘 做大事和做小事的难度是一样的.两者都会消耗你的时间和精力,所以如果决心做事,就要做大事,要确保你的梦想值得追求,未来的收获可以配得上你的努力. 前言 上一篇文章 <My ...
- 《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)
1.简介 理想很丰满现实很骨感,在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这样的操作就 ...
- 《手把手教你》系列技巧篇(二十九)-java+ selenium自动化测试- Actions的相关操作上篇(详解教程)
1.简介 有些测试场景或者事件,Selenium根本就没有直接提供方法去操作,而且也不可能把各种测试场景都全面覆盖提供方法去操作.比如:就像鼠标悬停,一般测试场景鼠标悬停分两种常见,一种是鼠标悬停在某 ...
- 《手把手教你》系列技巧篇(四十七)-java+ selenium自动化测试-判断元素是否显示(详解教程)
1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...
随机推荐
- JavaScricp
常用对话框 1.alert(""):警告对话框,作用是弹出一个警告对话框 2.confirm(""):确定对话框,弹出一个带确定和取消按钮的对话框——确定返回t ...
- msysgit之git bash方便的复制粘贴,默认工作目录,窗口大小,提高速度等小窍门
桌面图标点鼠标右键,选择属性,修改工作目录到自己的git目录: 打开快速编辑,这时候鼠标左键可以随意选取文本,enter键复制.鼠标右键是粘贴.另外,粘贴的快捷键是 inerst键 修改默认窗口大小 ...
- FTF登入tiny210开发板
配置环境一: 第一步:安装虚拟机 1)安装虚拟机+Linux12.04 2)安装FTP软件 第二步:配置超级终端(串口) 1)开 ...
- Django Nginx+uwsgi 安装配置
使用 python manage.py runserver 来运行服务器.这只适用测试环境中使用. 正式发布的服务,我们需要一个可以稳定而持续的服务器,比如apache, Nginx, lighttp ...
- tornado_mongodb 连接和使用
tornado,mongodb 连接和使用,开始使用tornado3.2,mongodb2.6,pymongo-3.03遇到不少的麻烦.因为新版tornado与老版本的代码有很多变化,mongodb根 ...
- Core Data 使用映射模型
Core Data 使用映射模型 如果新版本的模型存在较复杂的更改,可以创建一个映射模型,通过该模型指定源模型如何映射到目标模型. 创建映射模型,新建File, Core Data 选择Mappin ...
- CC_STACKPROTECTOR防内核堆栈溢出补丁分析【转】
转自:https://yq.aliyun.com/articles/1723 摘要: 作者:王智通 CC_STACKPROTECT补丁是Tejun Heo在09年给主线kernel提交的一个用来防 ...
- C语言共用体(Union)
通过前面的讲解,我们知道结构体(Struct)是一种构造类型或复杂类型,它可以包含多个类型不同的成员.在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(Union),它的定义格式为: uni ...
- CentOS7 Nginx负载均衡
五台服务器 192.168.155.129 nginx反向代理服务器 192.168.155.130 apache+PHP服务器,PHP要使用mysql函数库,配置的时候就要指定mysql安装路径,所 ...
- SQL 语句格式
SELECT `menuid`, SUM(`num`)AS total, `storeid`, DATE_FORMAT(`dateline`,'%Y-%m-%d') days FROM loss WH ...