在网络编程中,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

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