udp连接特性:
- 无连接:可以不构成连接就进行通信
- 不可靠:数据并不能保证可靠性
- 面向数据报:每条数据有长度限制,整条数据发送整条数据接受,传输不灵活,但是不会存在粘包问题。
原理在网络版块讲解
udp通信流程
c++封装udp接口,封装接口便于我们更好的实现
1 /*
2 *udp的封装接口
3 */
4 #include <iostream>
5 #include <string>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <sys/socket.h>
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13
14 class UdpSocket{
15 public:
16 UdpSocket():_socket(-1){
17 };
18 ~UdpSocket(){
19 };
20 //创建socket
21 bool Socket(){
22 _socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
23 if(_socket < 0){
26 }
27 return true;
28 }
29 //绑定连接
30 bool Bind(std::string ip,uint16_t port){
31 struct sockaddr_in addr;
32 addr.sin_family = AF_INET;
33 addr.sin_port = htons(port);
34 addr.sin_addr.s_addr = inet_addr(ip.c_str());
35
36 int len = sizeof(addr);
37
38 int ret = bind(_socket,(struct sockaddr*)&addr,len);
39 if(ret < 0){
40 perror("bind error\n");
41 return false;
42 }
43 return true;
44 }
45 //接受数据
46 bool Recv(std::string &buf,struct sockaddr_in *saddr){
47 //*daddr是发送的ip信息
48 // ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
49 // struct sockaddr *src_addr, socklen_t *addrlen);
50 char temp[1500];
51 socklen_t len = sizeof(struct sockaddr_in);
53 if(ret < 0){
54 perror("recvfrom error\n");
55 return false;
56 }
57 buf.assign(temp,ret);
58 return true;
59 }
60 //发送数据
61 bool Send(std::string& str,struct sockaddr_in* daddr){
62 // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
63 // const struct sockaddr *dest_addr, socklen_t addrlen);
64 int len = sizeof(struct sockaddr_in);
65 int ret = sendto(_socket,str.c_str(),str.size(),0
66 ,(struct sockaddr*)daddr,len);
67 if(ret < 0){
68 perror("sendto error\n");
69 return false;
70 }
71 return true;
72 }
73 //关闭连接
74 bool Close(){
75 close(_socket);
76 _socket = -1;
77 }
78 private:
79 int _socket;
80 };
udp服务端的实现
4 #include "udpsocket.hpp"
5 #define CHECK(T) if(!T) {return -1;}
6 int main(int argc,char* argv[]){
1 /*
2 *实现udp服务器端
3 */
4 #include "udpsocket.hpp"
5 #define CHECK(T) if(!T) {return -1;}
6 int main(int argc,char* argv[]){
7 //将我们的ip地址通过参数进行传递
8 if(argc < 3){
9 perror("./a.out ip port\n");
10 return -1;
11 }
12 std::string ip = argv[1];//ip地址的信息
13 uint16_t port = atoi(argv[2]);//port端口信息
14 //创建封装的类
15 UdpSocket sock;
16 //创建我们的套接字
17 CHECK(sock.Socket());
18 //绑定
19 CHECK(sock.Bind(ip,port));
20 while(1){
21 //接受数据
22 std::string str;
23 struct sockaddr_in client_addr;
24 CHECK(sock.Recv(str,&client_addr));
25 std::cout<<"client said:"<<str<<std::endl;
26 std::string answer;
27 std::cout<<"server say:";
28 fflush(stdout);
29 std::cin>>answer;
30 CHECK(sock.Send(answer,&client_addr));
31 }
32 sock.Close();
33 return 0;
34 }
udp客户端代码实现
1 /*
2 udp客户端程序实现
3 */
4 #include "udpsocket.hpp"
5
6 #define CHECK(T) if(!T) {return -1;}
7 int main(int argc,char* argv[]){
8 if(argc < 3){
9 perror("./a.out ip port\n");
1 /*
2 udp客户端程序实现
3 */
4 #include "udpsocket.hpp"
5
6 #define CHECK(T) if(!T) {return -1;}
7 int main(int argc,char* argv[]){
8 if(argc < 3){
9 perror("./a.out ip port\n");
10 return -1;
11 }
12 std::string ip = argv[1];
13 uint16_t port = atoi(argv[2]);
14
15 UdpSocket sock;
16 //创建套接字
17 CHECK(sock.Socket());
18 //客户端不用创建连接,绑定的是绑定的服务器端的地址信息
19 struct sockaddr_in ser_addr;
20 ser_addr.sin_family = AF_INET;
21 ser_addr.sin_port = htons(port);
22 ser_addr.sin_addr.s_addr = inet_addr(ip.c_str());
23
24 while(1){
25 //发送数据
26 std::string str;
27 std::cout<<"client say:";
28 fflush(stdout);
29 std::cin>>str;
30 CHECK(sock.Send(str,&ser_addr));
31 std::string answer;
32 CHECK(sock.Recv(answer,&ser_addr));
33 std::cout<<"server said:"<<answer<<std::endl;
34 }
35 sock.Close();
36 return 0;
37 }