开发环境
1、讯为RK3568开发板,下载了Ubuntu系统。
2、笔记本Windows下的VScode连接开发板。
3、网线连接开发板J13网口。
VSCode远程连接开发板 :https://blog.csdn.net/u012507643/article/details/152666866?spm=1011.2124.3001.6209
UDP收发的流程:
创建socket->bind->sendto/recvfrom
一、用到的函数
1、创建
#include <sys/socket.h>
#include <sys/types.h>
int socket(int domain, int type, int protocol);
1)domain协议族:用到的AF_INET、AF_INET6和PF_CAN、其他。
2)type套接字:
SOCK_STREAM面向连接、双向可靠字节流TCP
SOCK_DGRAM无连接、不可靠、固定长度的数据报UDP
SOCK_RAM原始套接字,允许访问底层协议IP、ICMP、CAN
SOCK_SEQPACKET可靠、连接、固定长度通讯报
3)protocol协议类型
通常设置0【自动选择合适的协议】。
IP 转换
将带'.'或者':'的ip字符串转换成二进制数据指针:[af:协议类型]
就是将字符串的IP地址转换成网络字节。
int inet_pton(int af, const char *src, void *dst);
af: AF_INET
src:"192.168.1.23"
dst: struct in_addr
将二进制数据指针ip转换成带'.'或者':'的ip字符串:[af:协议类型]
char *inet_ntop(int af, cosnt void *src, char *dst, socklen_t size);
端口号转换
16位主机字节序转换成网络字节序
uint16_t htons(uint16_t hostshort);
16位网络字节序转换成16位主机字节序
uint16_t ntohs(uint16_t netshort);
2、绑定端口
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:是socket函数返回的描述符
addr指向struct sockaddr。使用sockaddr_in后用强制转换成struct sockaddr。
struct sockaddr_in {
sa_family_t sin_family;//地址族
in_port_t sin_port;//端口号(需要用htons转换)
struct in_addr sin_addr;//ip地址(in_addr仅含一个32位整数s_addr)
char sin_zero[8];//填充字段,一帮为0
};
绑定示例:
struct sockaddr_in s;
s. sin_family = AF_INET;
s. sin_port = htons(8080);
inet_pton(AF_INET, "192.168.1.23", s. sin_addr);
bind(sockfd, (const struct sockaddr *)&s, sizeof(s));
3、收发
recvfrom和sendto这两个函数实际编程时候,看函数定义即可。
二、实际代码
#include <stdio.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd;
int port = 8080;
struct sockaddr_in s, rs;
char tx_buf[1024] = {0};
char rx_buf[1024] = {0};
ssize_t rlen = 0;
if (argc > 2)
{
port = atoi(argv[2]);
}
else
{
printf("参数2为端口号,未输入默认8080\n");
}
//SOCK_DGRAM:UDP
fd = socket(AF_INET, SOCK_DGRAM, 0);
/* 设置本地IP和端口 */
rs.sin_family = AF_INET;
rs.sin_port = htons(8081);
inet_pton(AF_INET, "192.168.31.96", &rs.sin_addr);
/* 这里绑定本机IP和端口 */
bind(fd, (const struct sockaddr *)&rs, sizeof(rs));
/* 设置远程IP和端口 */
s.sin_family = AF_INET;
s.sin_port = htons(port);
if (argc > 1)
{
inet_pton(AF_INET, argv[1], &s.sin_addr);
}
else
{
printf("参数1为ip地址,未输入默认192.168.31.98\n");
inet_pton(AF_INET, "192.168.31.98", &s.sin_addr);
}
int len = 10;
printf("本地IP:192.168.31.96,端口:8081\r\n等待接收远程数据\r\n");
while(1)
{
len = sizeof(rs);
rlen = recvfrom(fd, rx_buf, sizeof(rx_buf), MSG_DONTWAIT, (struct sockaddr *)&rs, (socklen_t *)&len);
if (rlen > 0 )
{
sendto(fd, rx_buf, strlen(rx_buf), MSG_DONTWAIT, (const struct sockaddr *)&s, sizeof(s));
// memset(tx_buf, 0, sizeof(tx_buf));
printf("recv:%s,len=%d\n", rx_buf, (int)rlen);
memset(rx_buf, 0 , sizeof(rx_buf));
}
}
return 0;
}
笔记本IP:192.168.31.20:8080。开发板IP:192.168.31.96:8081程序里面bind的地址

开发板运行:

笔记本发送,开发板应答,至此udp的收发完成:

三、总结
这里只是发的话还比较简单,我加了收,需要注意:
①、收的话需要bind另外定义一个结构体,bind开发板的IP和端口号,用于接受远程的udp数据包。
②、strutct sockaddr实际我们使用struct sockaddr_in 然后再进行强制转换。注意操作方便一点。
由于本人也是刚学,写的不好,也不规范,有错误的地方望前辈指正,以免误入歧途。