软件环境:vivado 2017.4 硬件平台:XC7Z020
工程与前一篇linux下操作axi_uartlite用的是同一个工程,所以网口自然用的是PS端的网口,主要是想要说明zynq平台linux下怎样通过网口收发udp的数据。
由于用的是PS端的网口,所以设备树中PS部分没有什么需要修改的地方,默认生成的就行。也没啥额外需要注意的,直接撸代码。
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char **argv)
{
int n = 0;
char recvline[1500] = {0};
int sockfd;
int peer_len = sizeof(struct sockaddr_in);
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
/* 创建一个UDP连接的socket */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
/*server_addr初始化*/
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(9000);
bzero(&client_addr, sizeof(client_addr));
/* 绑定server_addr初始化到创建的socketfd上 */
bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
while(1)
{
/*接收数据并通过client_addr获取源相关信息*/
n = recvfrom(sockfd, recvline, sizeof(recvline), 0, (struct sockaddr *)&client_addr, &peer_len);
/*将接收到的数据发回给源*/
sendto(sockfd, recvline, n, 0, (struct sockaddr *)&client_addr, peer_len);
memset(recvline, 0, sizeof(recvline));
}
/* 关闭socket连接 */
close(sockfd);
return 0;
}
首先需要先创建两个与socket有关的sockaddr_in结构体,用于绑定本地socket信息和接收源socket信息。
struct sockaddr_in
{
sa_family_t sin_family; //地址族
uint16_t sin_port; //16位TCP/UDP端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用
}
然后使用socket(AF_INET, SOCK_DGRAM, 0);来获取socket句柄,并利用server_addr初始化本地socket相关信息,INADDR_ANY绑定本机所有IP地址,监听本机所有IP地址上的9000端口。
利用bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));将初始化的句柄和本地socket信息绑定在一起。
接下来进入主函数了,主要也就是利用recvfrom()接收信息,利用sendto()发送信息,这里需要注意,默认情况下,recvfrom()是阻塞模式,也就是说,程序会一直卡在recvfrom()这里,直到接收到数据才向下执行。
ssize_t recvfrom(int sock, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
//sock:索引将要从其接收数据的套接字
//buf:存放消息接收后的缓冲区
//len:buf所指缓冲区的容量
//flags:操作标志,不同标志完成不同动作
//from:指向存放发送方地址的区域,如果为NULL,不储存发送方地址
//fromlen:作为输入参数,指向存放表示from最大容量的内存单元。作为输出参数,指向存放from实际长度的内存单元
ssize_t sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
//sock:索引将要从其发送数据的套接字
//buf:指向将要发送数据的缓冲区
//len:buf所指缓冲区的容量
//flags:操作标志,不同标志完成不同动作
//to:指向存放接收方地址的区域,可以为NULL
//tolen:以上内存区的长度,可以为0
发送的函数出了sendto之外,还有send可以用,跟sendto差不多。
ssize_t send(int sock, const void *buf, size_t len, int flags);
这里主要还是贴直接就能使用的代码,至于socket建立的整个原理呀,flag参数详细的意义呀,等等等等,一方面可以百度,另一方面,实际试试,操作下就知道各个参数都有什么影响了。
代码达到的效果就是,发送给板子什么UDP信息,板子就回给PC什么UDP信息。类似于echo msg。
放心吧~贴上来的代码,都是实测过的~!没问题的~