在網絡編程中,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 |
上述代碼是經過驗證可用的。