udp 协议是一种无链接的不可靠传输协议,且UDP每次发送到分组数据大小都是固定的,它的主要特点如下:
UDP之所以为不可靠传输协议,主要还是因为UDP没有链接和应答机制,导致UDP在发送数据的时候根本不清楚通信线路的连接情况,所有通过UDP发送数据的时候无法保证数据一定能够发送给对方。因此UDP时不可靠的传输协议
UDP协议每次传输数据时,必须指定对方的IP和端口号
因为udp没有连接的特性,所有UDP协议没有自动记录对方ip和端口号的特点,因为每次发送数据事,应用程序必须亲自指定对方的ip和端口号,只有这样才能将数据发送给对方。
如果是跨网通信,指定的ip就是对方的路由器公网ip
UDP 编程模型非常简单,通信双发的实现基本一致,且没有服务器的概念,如下图
AF_INET
SOCK_DGRAM
bind
函数和自己的ip和端口进行绑定sendto
函数向对方发送数据,这里需要注意的是sendto
函数需要填写对方ip和端口号的参数,因为udp通信时需要明确对方设备的ip和端口,所以发送数据包的时候需要对对方的ip和端口号进行指定struct sockaddr
将会指定消息的来源。PS:两个通信进程在同一主机不能出现端口冲突,所以以下代码测试是在同一主机上,此时需要设置不同的端口。
UDP_A.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #define IP "192.168.102.174"
#define PORT 6000typedef struct data { char name[30];unsigned int num;
}Data;void print_err(char *str, int line, int err_no) { printf("%d, %s :%s
",line,str,strerror(err_no));_exit(-1);
}int cfd = -1;
//接收线程函数
void *receive(void *pth_arg) { int ret = 0;Data stu_data = { 0};struct sockaddr_in addr0 = { 0};int addr0_size = sizeof(addr0);//从对端ip和端口号中接收消息,指定addr0用于存放消息while(1) { bzero(&stu_data, sizeof(stu_data));ret = recvfrom(cfd, &stu_data, sizeof(stu_data),0, (struct sockaddr *)&addr0, &addr0_size); if (-1 == ret) { print_err("recv failed",__LINE__,errno);}else if (ret > 0){ printf("student number = %d student name = %s
",ntohl(stu_data.num),stu_data.name);//打印对方的消息和端口号printf("ip %s,port %d
",inet_ntoa(addr0.sin_addr),ntohs(addr0.sin_port));}}
}int main()
{ int ret = -1;//创建tcp/ip协议族,指定通信方式为无链接不可靠的通信cfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == cfd) { print_err("socket failed", __LINE__, errno);}//进行端口号和ip的绑定struct sockaddr_in addr;addr.sin_family = AF_INET; //设置tcp协议族addr.sin_port = htons(PORT); //设置端口号addr.sin_addr.s_addr = inet_addr(IP); //设置ip地址ret = bind(cfd, (struct sockaddr*)&addr, sizeof(addr));if ( -1 == ret) { print_err("bind failed",__LINE__,errno);}//创建线程函数,用于处理数据接收pthread_t id;ret = pthread_create(&id,NULL,receive,NULL);if (-1 == ret) print_err("pthread_create failed", __LINE__, errno);struct sockaddr_in addr0;addr0.sin_family = AF_INET; //设置tcp协议族addr0.sin_port = htons(7000); //设置端口号addr0.sin_addr.s_addr = inet_addr(IP); //设置ip地址Data std_data = { 0};//发送消息while (1) { bzero(&std_data, sizeof(std_data));printf("stu name:
");scanf("%s",std_data.name);printf("stu num:
");scanf("%d",&std_data.num);std_data.num = htonl(std_data.num);//发送消息时需要绑定对方的ip和端口号 ret = sendto(cfd, (void *)&std_data,sizeof(std_data), 0, (struct sockaddr *)&addr0, sizeof(addr0));if ( -1 == ret) { print_err("accept failed", __LINE__, errno);} }return 0;
}
另一端的实现基本和UDP_A.c
一样,因为是本机测试,只有在发送的时候设置的端口号不一样。如果跨网通信,则需要设置发送时指定的ip为 对方路由器的公网ip
UDP_B.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #define IP "192.168.102.174"
#define PORT 7000typedef struct data { char name[30];unsigned int num;
}Data;void print_err(char *str, int line, int err_no) { printf("%d, %s :%s
",line,str,strerror(err_no));_exit(-1);
}int cfd = -1;
void *receive(void *pth_arg) { int ret = 0;Data stu_data = { 0};struct sockaddr_in addr0 = { 0};int addr0_size = sizeof(addr0);while(1) { bzero(&stu_data, sizeof(stu_data));ret = recvfrom(cfd, &stu_data, sizeof(stu_data),0, (struct sockaddr *)&addr0, &addr0_size); if (-1 == ret) { print_err("recv failed",__LINE__,errno);}else if (ret > 0){ printf("student number = %d student name = %s
",ntohl(stu_data.num),stu_data.name);printf("ip %s,port %d
",inet_ntoa(addr0.sin_addr),ntohs(addr0.sin_port));}}
}int main()
{ int ret = -1;cfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == cfd) { print_err("socket failed", __LINE__, errno);}struct sockaddr_in addr;addr.sin_family = AF_INET; //设置tcp协议族addr.sin_port = htons(PORT); //设置端口号addr.sin_addr.s_addr = inet_addr(IP); //设置ip地址ret = bind(cfd, (struct sockaddr*)&addr, sizeof(addr));if ( -1 == ret) { print_err("bind failed",__LINE__,errno);}pthread_t id;ret = pthread_create(&id,NULL,receive,NULL);if (-1 == ret) print_err("pthread_create failed", __LINE__, errno);struct sockaddr_in addr0;addr0.sin_family = AF_INET; //设置tcp协议族addr0.sin_port = htons(6000); //设置端口号addr0.sin_addr.s_addr = inet_addr(IP); //设置ip地址Data std_data = { 0};while (1) { bzero(&std_data, sizeof(std_data));printf("stu name:
");scanf("%s",std_data.name);printf("stu num:
");scanf("%d",&std_data.num);std_data.num = htonl(std_data.num);ret = sendto(cfd, (void *)&std_data,sizeof(std_data), 0, (struct sockaddr *)&addr0, sizeof(addr0));if ( -1 == ret) { print_err("accept failed", __LINE__, errno);} }return 0;
}
编译运行:
gcc UDP_B.c -o B -pthread
gcc UDP_A.c -o A -pthread
运行如下:
下面的源码给出了使用boost::asio进行域名解析的方法.
//g++ -g resolver_demo.cpp -o resolver_demo -lboost_system -lpthread
//#include
pc 端配置 点击pc端无线链接图标编辑链接以太网编辑IPv4设置方法:与其他计算机共享根据putty获取的动态ip使用ssh登录 解决 ip 无法登录问题 设置 pc 端 ip 和开发板 ip 在同一个网段 比如开发板 ip 是 10.42.0.123 可以设置自己机器的 ip 为 10.42.0.11 sudo ifcon...
原文:TCP/IP 简介 第一节:TCP/IP 简介 第二节:TCP/IP 寻址 第三节:TCP/IP 协议 第四节:TCP/IP 邮件 TCP/IP 是用于因特网 (Internet) 的通信协议。 计算机通信协议 计算机通信协议是对那些计算机必须遵守以便彼此通信的规则的描述。 什么是 TC...
#保存一万条命令记录 sed -i 's/^HISTSIZE=1000/HISTSIZE=10000/g' /etc/profile#在/etc/profile的文件尾部添加如下行数配置信息 ######jiagu history xianshi######### USER_IP=`who -u am i 2>/dev/null |...
TCP/IP基础概念及通信过程举例 出现 上个世纪60年代,由于中央集中式网络的容灾性较弱,以美国国防部为中心的一家组织研究出分组交换网络。后来为了验证分组交换技术的实用性,ARPANET出现了,并且在3年内逐渐发展,由4个节点发展至34个节点。20世纪70年代前半叶,ARPANET一个机构研制出了TCP/IP,1982年具体规范...
关于点云的分割算是我想做的机械臂抓取中十分重要的俄一部分,所以首先学习如果使用点云库处理我用kinect获取的点云的数据,本例程也是我自己慢慢修改程序并结合官方API 的解说实现的,其中有很多细节如果直接更改源程序,可能会因为数据类型,或者头文件等各种原因编译不过,会导致我们比较难得找出其中的错误,首先我们看一下我自己设定的一个场景,...
/*
使用正态分布变换进行配准的实验 。其中room_scan1.pcd room_scan2.pcd这些点云包含同一房间360不同视角的扫描数据
*/
#include
#include
#include
#include