(十四)UDP协议的两个主要方法sendto和recvfrom详解

在网络编程中,UDP运用非常广泛。很多网络协议是基于UDP来实现的,如SNMP等。大家常常用到的局域网文件传输软件飞鸽传书也是基于UDP实现的。

本篇文章跟大家分享linux下UDP的使用和实现,主要介绍下sendto()和recvfrom()两个函数的使用,以及INADDR_ANY的说明,并在最后展示了一个经过自己测试可用的UDP Server和UDP Client的代码示例。

关于UDP数据报

UDP都是以数据报的形式进行发送和接收的,而TCP是以数据流的形式进行发送和接收的。数据报和数据流,这两者要区分开来。

头文件

#include <sys/types.h>

#include <sys/socket.h>

函数原型

int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);

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:

view source

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

上述代码是经过验证可用的。

时间: 2024-08-11 01:36:07

(十四)UDP协议的两个主要方法sendto和recvfrom详解的相关文章

UDP协议的两个主要方法sendto和recvfrom详解

sendto() 简述:  向一指定目的地发送数据. #include <winsock.h> int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags,  const struct sockaddr FAR* to, int tolen); s:一个标识套接口的描述字.  buf:包含待发送数据的缓冲区.  len:buf缓冲区中数据的长度.  flags:调用方式标志位.  to:(可选)指针,指向目的

TCP/IP协议族——ARP、DNS工作原理及实例详解

 测试网络: 通过VMware创建了两个虚拟机,并利用桥接方式联网以此模拟两台主机连接一台路由器的情况.测试网络图如下: ARP协议工作原理 ARP协议能实现任意网络地址到任意物理地址的转换,这里仅讨论IP地址到以太网地址(MAC地址)的转换.其工作原理是:主机向自己所在网络广播一个ARP请求,该请求包含目标机器的网络地址.此网络上的其他机器都将接收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址. 以太网ARP请求/应答报文 以太网ARP请求/应答报文格式如下

马哥教育第二十四ftp协议、vsftpd的高级应用、rpc概念及nfs的基本应用、samba及其基本应用

1.ftp协议及vsftpd的基本应用         文件共享服务:                 工作在应用层:ftp(file transfer protocol)                          应用层协议:tcp,                  工作在内核:nfs                 跨平台:samba           ftp工作在221号端口,传输数据:                  命令连接:文件管理类命令,始终在线的连接       

JAVA学习第六十课 — UDP协议 &amp;基于多线程模拟简单的QQ聊天程序

UDP传输 UDP有发送端和接受端,有两大类,DatagramSocket.DatagramPacket 建立发送端和接收端 建立数据包 调用Socket的接收发送方法 关闭Socket 注意:发送端和接收端是两个独立的运行程序 UDP发送端演示 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号. public static voi

第十四章:类的带参方法

1. 语法 <访问修饰符>返回值类型<方法名>(<参数列表>){ //方法的主体} <访问修饰符>:指该方法允许被访问的权限范围,只能是public.protected或private.其中public访问修饰符表示该方法可以被任何其他代码调用. 返回值类型:指方法返回值的类型.如果方法不返回任何值,它应该声明为void类型. <方法名>:是定义的方法的名字,它必须使用合法的标识符. <参数列表>:是传送给方法的参数列表.列表中各参数

MySQL数据库中备份相关的两种工具--mysqlbinlog和mysqldump使用详解

一.mysqldump 对数据库做完整备份命令格式: #mysqldump  -h服务器ip  -u用户名  -p密码备份对象> /dbdir/文件名.sql   说明: 1.不指定路径存储在当前目录下: 2./dbdir需提前创建: 3.文件名要有标识性,备份文件不能重名,否则会覆盖.做计划任务时用date获取日期做文件名: 00 02 * * 1 mysqldump  -hlocalhost -uroot  -p123  --all- databases> /dbdir/db.a-$(da

Dynamic CRM 2013学习笔记(三十八)流程1 - 操作(action)开发与配置详解

CRM 2013 里流程有4个类别:操作(action).业务流程(business process flow).对话(dialog)和工作流(workflow).它们都是从 setting –> Process 进入,然后点击New按钮来创建: 这篇主要介绍操作:什么是操作.什么时候使用操作.如何创建以及如何调用 一.什么是操作 操作是CRM 2013 新增加的一个功能,用来扩展系统的标准功能.业务人员可以用它来实现业务逻辑,然后开发人员可以在系统事件里(比如update,create)来使用

Oracle两种临时表的创建与使用详解

ORACLE数据库除了可以保存永久表外,还可以建立临时表temporary tables.这些临时表用来保存一个会话SESSION的数据,或者保存在一个事务中需要的数据.当会话退出或者用户提交commit和回滚rollback事务的时候,临时表的数据自动清空,但是临时表的结构以及元数据还存储在用户的数据字典中. 分类: 1.会话级临时表 会话级临时表是指临时表中的数据只在会话生命周期之中存在,当用户退出会话结束的时候,Oracle自动清除临时表中数据. 格式: Create Global Tem

Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)

简介 前边一直在分享testng的相关文章,看了点赞量和阅读数不是很高,宏哥猜测估计是大家确实是用不到或者不喜欢吧!不过宏哥经过一段时间的准备,appium的自动化测试框架完善的差不多了,那么接下来宏哥继续给小伙伴和童鞋们分享有关Appium自动化测试框架综合实践.想必小伙伴们有点等不及了吧! driver配置封装 kyb_caps.yaml 配置表 主要是一些配置信息的封装. 参考代码 platformName: Android #模拟器 platformVersion: 5.1.1 devi