UDP sendto和recvfrom使用详解
在网络编程中,UDP运用非常广泛。很多网络协议是基于UDP来实现的,如SNMP等。大家常常用到的局域网文件传输软件飞鸽传书也是基于UDP实现的。
本篇文章跟大家分享linux下UDP的使用和实现,主要介绍下sendto()和recvfrom()两个函数的使用,以及INADDR_ANY的说明,并在最后展示了一个经过自己测试可用的UDP Server和UDP Client的代码示例。
头文件
1
|
#include <sys/types.h>
|
2
|
#include <sys/socket.h>
|
函数原型
1
|
int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);
|
2
|
3
|
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)。
- \fromlen:recvfrom()函数参数,struct sockaddr_in类型,指明从哪里接收UDP数据报。
函数返回值
对于sendto()函数,成功则返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。
对于recvfrom()函数,成功则返回接收到的字符数,失败则返回-1,错误原因存于errno中。
struct sockaddr_in结构体
该结构体的定义如下:
01
|
/* Structure describing an Internet (IP) socket address. */
|
02
|
#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
|
03
|
struct sockaddr_in {
|
04
|
sa_family_t sin_family; /* Address family */
|
05
|
__be16 sin_port; /* Port number */
|
06
|
struct in_addr sin_addr; /* Internet address */
|
07
|
08
|
/* Pad to size of `struct sockaddr'. */
|
09
|
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
|
10
|
sizeof(unsigned short int) - sizeof(struct in_addr)];
|
11
|
};
|
其中,sin_family指明地址族,一般使用AF_INET:
1
|
#define AF_INET 2 /* Internet IP Protocol */
|
sin_port:指明UDP端口;sin_addr指明IP地址:
1
|
/* Internet address. */
|
2
|
struct in_addr {
|
3
|
__be32 s_addr;
|
4
|
};
|
INADDR_ANY说明
INADDR_ANY,是个特殊IP地址 ,表示任务的IP地址,作为服务器端的时候经常要用到。对于它的解释,摘用下面一段英文(来自于:http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html):
When you wrote your simple FTP server in project 1, you probably bound your listening socket to the special IP address INADDR_ANY. This allowed your program to work without knowing the IP address of the machine it was running on, or, in the case of a machine with multiple network interfaces, it allowed your server to receive packets destined to any of the interfaces. In reality, the semantics of INADDR_ANY are more complex and involved.
In the simulator, INADDR_ANY has the following semantics: When receiving, a socket bound to this address receives packets from all interfaces. For example, suppose that a host has interfaces 0, 1 and 2. If a UDP socket on this host is bound using INADDR_ANY and udp port 8000, then the socket will receive all packets for port 8000 that arrive on interfaces 0, 1, or 2. If a second socket attempts to Bind to port 8000 on interface 1, the Bind will fail since the first socket already “owns” that port/interface.
When sending, a socket bound with INADDR_ANY binds to the default IP address, which is that of the lowest-numbered interface.
大概的意思就是,作为接收端,当你调用bind()函数绑定IP时使用INADDR_ANY,表明接收来自任意IP、任意网卡的发给指定端口的数据。作为发送端,当用调用bind()函数绑定IP时使用INADDR_ANY,表明使用网卡号最低的网卡进行发送数据,也就是UDP数据广播。
关于UDP数据报
UDP都是以数据报的形式进行发送和接收的,而TCP是以数据流的形式进行发送和接收的。数据报和数据流,这两者要区分开来。
UDP Server和Client源码实例
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使用详解相关推荐
- TCP通信常用的send,sendto,recv,recvfrom函数详解
send函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函 ...
- python recvfrom函数详解_UDP sendto和recvfrom使用详解
在网络编程中,UDP运用非常广泛.很多网络协议是基于UDP来实现的,如SNMP等.大家常常用到的局域网文件传输软件飞鸽传书也是基于UDP实现的. 本篇文章跟大家分享linux下UDP的使用和实现, ...
- linux中recvfrom读取速度,Linux系统调用-- recv/recvfrom 函数详解
Linux系统调用-- recv/recvfrom函数详解 功能描述: 从套接字上接收一个消息.对于recvfrom,可同时应用于面向连接的和无连接的套接字.recv一般只用在面向连接的套接字,几乎等 ...
- linux内核 recvfrom,Linux系统调用-- recv/recvfrom 函数详解
Linux系统调用-- recv/recvfrom函数详解 功能描述: 从套接字上接收一个消息.对于recvfrom,可同时应用于面向连接的和无连接的套接字.recv一般只用在面向连接的套接字,几乎等 ...
- UDP和TCP的报文详解
TCP和UDP报文详解 一.先说说端口号 TCP和UDP都是位于传输层的协议,传输层负责将数据从发送端传输到接收端. 端口号(Port)标识了一台主机上正在进行通信的一个具体的应用程序,在TCP/IP ...
- UDP数据包协议格式详解
源端口目的端口:是0-65535任何数字,在收到请求时系统会为客户端动态分配,0-1023为知名端口号 报文长度(单位4byte):表示udp报头+udp数据总长度,有别于tcp,也没有选项 UDP报 ...
- 计算机网络【UDP和TCP首部字段详解】
文章目录 一 UDP详解 二 TCP首部各个字段详解 一 UDP详解 在传输层中,有两个协议UDP和TCP,通常UDP都是比较简单的协议字段,因为UDP不需要面向连接,也就是说,发送UDP数据包过去时 ...
- python recvfrom函数详解_UDP协议的两个主要方法sendto和recvfrom详解
简述: 接收一个数据报并保存源地址. #include int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags, st ...
- 网络 传输层 | UDP协议与TCP协议详解(三次握手及四次挥手、滑动窗口、拥塞控制)
概念 传输层:是负责应用程序之间的数据传输(通过端口的描述,描述了哪两个进程间的通信):传输层的两个主要协议:UDP 和 TCP UDP协议 UDP协议全称:用户数据报协议(User Dategram ...
最新文章
- 编译 ioftpd v7.7.3
- 在SQL2005/SQL2008中CTE用法差异
- 将CSDN600W用户及密码帐号存入本地MySql数据库
- 【自定义排序规则】剑指 Offer 45. 把数组排成最小的数
- XMPP之openfire无法启动
- 免费个人博客:使用hexo+github搭建详细教程
- opengl es的射线拾取
- Java Web学习总结(14)——JSP基础语法
- 第二:python安装校验报错api-ms-win-crt-process-l1-1-0.dll 丢失的处理
- 第八讲:1602液晶(郭天祥)
- 五到十分钟java演讲_10分钟励志演讲稿5篇最新
- vue2编译报错Class constructor VuexModule cannot be invoked without ‘new‘
- 网络隔离下的几种数据交换技术比较
- 正六边形:判断点是否在正六边形内
- 结合实战,浅析GB/T28181(七)—— 球机云台控制
- C# NPOI 导出Excel
- ANO V7上位机协议程序(新版加入DMA形式发送接收)
- Java URI 和 android Uri 中的 getSchemeSpecificPart() 方法
- 脉冲神经网络克服了类脑计算的硬件障碍,让AI更节能
- 文献阅读笔记:Homogeneous ice nucleation in an ab initio machine-learning model of water
热门文章
- 电脑的发展史_互联网发展史 硅谷传奇之 IBM
- 用c语言产生大素数,C语言实现寻找大素数
- oracle 递归计算,SQL(Oracle)中的递归计算
- 循环发ajax请求,在循环中发送jquery ajax请求
- win7计算机个性化设置,笔记本电脑windows7系统如何用好电脑个性化设置
- mysql中常见查询表_MySQL中常见查询
- python中函数参数_Python函数的参数
- 国家开放大学2021春1087数学分析专题研究题目
- 【渝粤教育】广东开放大学 网络完全与技术 形成性考核 (44)
- 【案例分享】无线唤醒技术在灌溉系统上的应用案例