途牛网网站建设评价,网页传奇手游官网,装修设计咨询公司,网站seo诊断工具UDP 是User Datagram Protocol 的简称#xff0c;中文名是用户数据报协议#xff0c;是一种无连接、不可靠的协议#xff0c;同样它也是工作在传顺层。它只是简单地实现从一端主机到另一端主机的数据传输功能#xff0c;这些数据通过 IP 层发送#xff0c;在网络中传输中文名是用户数据报协议是一种无连接、不可靠的协议同样它也是工作在传顺层。它只是简单地实现从一端主机到另一端主机的数据传输功能这些数据通过 IP 层发送在网络中传输到达目标主机的顺序是无法预知的因此需要应用程序对这些数据进行排序处理这就带来了很大的不方便此外UDP 协议更没有流量控制、拥塞控制等功能在发送的一端UDP 只是把上层应用的数据封装到UDP 报文中在差错检测方面仅仅是对数据进行了简单的校验然后将其封装到 IP 数据报中发送出去。而在接收端无论是否收到数据它都不会产生一个应答发送给源主机并且如果接收到数据发送校验错误那么接收端就会丢弃该UDP 报文也不会告诉源主机这样子传输的数据是无法保障其准确性的如果想要其准确性那么就需要应用程序来保障了。
UDP 协议的特点
无连接、不可靠尽可能提供交付数据服务出现差错直接丢弃无反馈 面向报文发送方的UDP 拿到上层数据直接添加个UDP 首部然后进行校验后就递交给 IP 层而接收的一方在接收到UDP 报文后简单进行校验然后直接去除数据递交给上层应用 速度快因为UDP 协议没有TCP 协议的握手、确认、窗口、重传、拥塞控制等机制UDP 是一个无状态的传输协议所以它在传递数据时非常快即使在网络拥塞的时候UDP 也不会降低发送的数据。 UDP 虽然有很多缺点但也有自己的优点所以它也有很多的应用场合因为在如今的网络环境下 UDP 协议传输出现错误的概率是很小的并且它的实时性是非常好常用于实时视频的传输比如直播、网络电话等因为即使是出现了数据丢失的情况导致视频卡帧这也不是什么大不了的事情所以UDP协议还是会被应用与对传输速度有要求并且可以容忍出现差错的数据传输中。
在Linux使用socket网络编程实现udp通信流程如下
1. 初始化socket
int sock_fd socket(AF_INET , SOCK_DGRAM , 0);
if(sock_fd 0){perror(failed to open socket);return -1;
}
2. 绑定IP和端口号
/** 绑定IP和端口号 */
struct sockaddr_in server_addr;
server_addr.sin_family AF_INET;
server_addr.sin_addr.s_addr INADDR_ANY; // 本地任意IP
server_addr.sin_port htons(8888); // 指定端口号
int ret bind(sock_fd, (struct sockaddr *)server_addr, sizeof(server_addr));
if(ret 0)
{perror(failed to bind);close(sock_fd);return -1;
}
3. 设置组播接收可选
std::string multi_addr 224.0.0.10;
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr inet_addr(multi_addr.c_str());
mreq.imr_interface.s_addr INADDR_ANY;
ret setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq, sizeof(struct ip_mreq));
if (0 ret)
{perror(set socket multicast error);return false;
}
4. 设置接收超时可选
/** 设置接收超时可选 */
int mill_sec 2000; // 毫秒
struct timeval time_out;
time_out.tv_sec mill_sec / 1000;
time_out.tv_usec (mill_sec- time_out.tv_sec * 1000) * 1000;
ret setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,time_out,sizeof (timeval));
if(ret 0)
{perror(udp setTimeOut error!);
}
5. 发送数据
unsigned char buf[1024];
std::string ip 192.168.1.10;
int port 1234;
struct sockaddr_in client{};
memset(client, 0, sizeof(client));
client.sin_addr.s_addr inet_addr(ip.c_str());
client.sin_family AF_INET;
client.sin_port htons(port);
ret sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_caststruct sockaddr *(client), sizeof(struct sockaddr));
if(ret 0){perror(udpServer send error!);
}else{std::cout send success! std::endl;
}
6. 接收数据
unsigned char buffer[1024];
struct sockaddr_in addr;
socklen_t addr_len sizeof(addr);
while(true)
{memset(buffer, 0, sizeof(buffer));ssize_t len recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_caststruct sockaddr *(addr), addr_len);if(len 0){std::cout received message len : len std::endl;}else{perror(recv error);}
}
7. 完整代码
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include netdb.h
#include netdb.h
#include net/if.h
#include sys/types.h
#include stdio.h
#include unistd.h
#include iostream
#include cstring
#include threadvoid recv_func(int sock_fd_)
{
unsigned char buffer[1024];
struct sockaddr_in addr;
socklen_t addr_len sizeof(addr);
while(true)
{memset(buffer, 0, sizeof(buffer));ssize_t len recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_caststruct sockaddr *(addr), addr_len);if(len 0){std::cout received message len : len std::endl;}else{perror(recv error);}
}
}int main(int agrc, char** argv)
{int sock_fd socket(AF_INET , SOCK_DGRAM , 0); if(sock_fd 0){perror(failed to open socket);return -1;}/** 绑定IP和端口号 */ struct sockaddr_in server_addr;server_addr.sin_family AF_INET;server_addr.sin_addr.s_addr INADDR_ANY; // 本地任意IPserver_addr.sin_port htons(8888); // 指定端口号int ret bind(sock_fd, (struct sockaddr *)server_addr, sizeof(server_addr));if(ret 0){perror(failed to bind);close(sock_fd);return -1;}/** 设置组播接收 (可选)*/
std::string multi_addr 224.0.0.10;
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr inet_addr(multi_addr.c_str());
mreq.imr_interface.s_addr INADDR_ANY;
ret setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq, sizeof(struct ip_mreq));
if (0 ret)
{perror(set socket multicast error);return false;
}/** 设置接收超时可选 */
int mill_sec 2000; // 毫秒
struct timeval time_out;
time_out.tv_sec mill_sec / 1000;
time_out.tv_usec (mill_sec- time_out.tv_sec * 1000) * 1000;
ret setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,time_out,sizeof (timeval));
if(ret 0)
{perror(udp setTimeOut error!);
}/** 开启线程接收 */std::thread recv_t(recv_func, sock_fd);recv_t.detach();/** 主线程发送 */while (true){
unsigned char buf[1024];
std::string ip 192.168.1.10;
int port 1234;
struct sockaddr_in client{};
memset(client, 0, sizeof(client));
client.sin_addr.s_addr inet_addr(ip.c_str());
client.sin_family AF_INET;
client.sin_port htons(port);
ret sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_caststruct sockaddr *(client), sizeof(struct sockaddr));
if(ret 0){perror(udpServer send error!);
}else{std::cout send success! std::endl;
}usleep(50*1000);}
}
8. 编译运行
# 编译
g udp_main.cpp -o main -lpthread
# 运行
./main