大家好,又见面了,我是你们的朋友全栈君。
UDP(user datagram protocol)用户数据报协议,属于传输层。
UDP是面向非连接的协议,它不与对方建立连接,而是直接把数据报发给对方。UDP无需建立类如三次握手的连接,使得通信效率很高。因此UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。
UDP通信的过程如图所示:
服务端:
(1)使用函数socket(),生成套接字文件描述符;
(2)通过struct sockaddr_in 结构设置服务器地址和监听端口;
(3)使用bind() 函数绑定监听端口,将套接字文件描述符和地址类型变量(struct sockaddr_in )进行绑定;
(4)接收客户端的数据,使用recvfrom() 函数接收客户端的网络数据;
(5)向客户端发送数据,使用sendto() 函数向服务器主机发送数据;
(6)关闭套接字,使用close() 函数释放资源;
客户端:
(1)使用socket(),生成套接字文件描述符;
(2)通过struct sockaddr_in 结构设置服务器地址和监听端口;
(3)向服务器发送数据,sendto() ;
(4)接收服务器的数据,recvfrom() ;
(5)关闭套接字,close() ;
(关于 sockaddr 与 sockaddr_in 的区别,可参考:https://blog.csdn.net/qingzhuyuxian/article/details/79736821)
sendto()
代码语言:javascript复制1 1 int sendto(int s, const void *buf, int len, unsigned int flags, 2 const struct sockaddr *to, int tolen);
返回值说明:
成功则返回实际传送出去的字符数,失败返回-1,错误原因会存于errno 中。
参数说明:
s: socket描述符; buf: UDP数据报缓存区(包含待发送数据); len: UDP数据报的长度; flags:调用方式标志位(一般设置为0); to: 指向接收数据的主机地址信息的结构体(sockaddr_in需类型转换); tolen:to所指结构体的长度;
recvfrom()
代码语言:javascript复制1 int recvfrom(int s, void *buf, int len, unsigned int flags, 2 struct sockaddr *from, int *fromlen);
返回值说明:
成功则返回实际接收到的字符数,失败返回-1,错误原因会存于errno 中。
参数说明:
s: socket描述符; buf: UDP数据报缓存区(包含所接收的数据); len: 缓冲区长度。 flags: 调用操作方式(一般设置为0)。 from: 指向发送数据的客户端地址信息的结构体(sockaddr_in需类型转换); fromlen:指针,指向from结构体长度值。
示例代码
服务端
代码语言:javascript复制 1 #include <unistd.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <iostream>
5 #include <netinet/in.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9
10 #define MAXLINE 4096
11 #define UDPPORT 8001
12 #define SERVERIP "192.168.255.129"
13
14 using namespace std;
15
16 int main(){
17 int serverfd;
18 unsigned int server_addr_length, client_addr_length;
19 char recvline[MAXLINE];
20 char sendline[MAXLINE];
21 struct sockaddr_in serveraddr , clientaddr;
22
23 // 使用函数socket(),生成套接字文件描述符;
24 if( (serverfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
25 perror("socket() error");
26 exit(1);
27 }
28
29 // 通过struct sockaddr_in 结构设置服务器地址和监听端口;
30 bzero(&serveraddr,sizeof(serveraddr));
31 serveraddr.sin_family = AF_INET;
32 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
33 serveraddr.sin_port = htons(UDPPORT);
34 server_addr_length = sizeof(serveraddr);
35
36 // 使用bind() 函数绑定监听端口,将套接字文件描述符和地址类型变量(struct sockaddr_in )进行绑定;
37 if( bind(serverfd, (struct sockaddr *) &serveraddr, server_addr_length) < 0){
38 perror("bind() error");
39 exit(1);
40 }
41
42 // 接收客户端的数据,使用recvfrom() 函数接收客户端的网络数据;
43 client_addr_length = sizeof(sockaddr_in);
44 int recv_length = 0;
45 recv_length = recvfrom(serverfd, recvline, sizeof(recvline), 0, (struct sockaddr *) &clientaddr, &client_addr_length);
46 cout << "recv_length = "<< recv_length <<endl;
47 cout << recvline << endl;
48
49 // 向客户端发送数据,使用sendto() 函数向服务器主机发送数据;
50 int send_length = 0;
51 sprintf(sendline, "hello client !");
52 send_length = sendto(serverfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &clientaddr, client_addr_length);
53 if( send_length < 0){
54 perror("sendto() error");
55 exit(1);
56 }
57 cout << "send_length = "<< send_length <<endl;
58
59 //关闭套接字,使用close() 函数释放资源;
60 close(serverfd);
61
62 return 0;
63 }
View Code
客户端
代码语言:javascript复制 1 #include <unistd.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <iostream>
5 #include <netinet/in.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9
10 #define MAXLINE 4096
11 #define UDPPORT 8001
12 #define SERVERIP "192.168.255.129"
13
14 using namespace std;
15
16 int main(){
17 int confd;
18 unsigned int addr_length;
19 char recvline[MAXLINE];
20 char sendline[MAXLINE];
21 struct sockaddr_in serveraddr;
22
23 // 使用socket(),生成套接字文件描述符;
24 if( (confd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ){
25 perror("socket() error");
26 exit(1);
27 }
28
29 //通过struct sockaddr_in 结构设置服务器地址和监听端口;
30 bzero(&serveraddr, sizeof(serveraddr));
31 serveraddr.sin_family = AF_INET;
32 serveraddr.sin_addr.s_addr = inet_addr(SERVERIP);
33 serveraddr.sin_port = htons(UDPPORT);
34 addr_length = sizeof(serveraddr);
35
36 // 向服务器发送数据,sendto() ;
37 int send_length = 0;
38 sprintf(sendline,"hello server!");
39 send_length = sendto(confd, sendline, sizeof(sendline), 0, (struct sockaddr *) &serveraddr, addr_length);
40 if(send_length < 0 ){
41 perror("sendto() error");
42 exit(1);
43 }
44 cout << "send_length = " << send_length << endl;
45
46 // 接收服务器的数据,recvfrom() ;
47 int recv_length = 0;
48 recv_length = recvfrom(confd, recvline, sizeof(recvline), 0, (struct sockaddr *) &serveraddr, &addr_length);
49 cout << "recv_length = " << recv_length <<endl;
50 cout << recvline << endl;
51
52 // 关闭套接字,close() ;
53 close(confd);
54
55 return 0;
56 }
View Code
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/155014.html原文链接:https://javaforall.cn