linux系统编程(十)RK3568 socket之 UDP的实现
开发环境
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:UDPfd = 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 然后再进行强制转换。注意操作方便一点。
由于本人也是刚学,写的不好,也不规范,有错误的地方望前辈指正,以免误入歧途。