这几乎是一个非常菜鸟的程序,但是搞了我半天。
最近一直在学习linux C++程序设计,于是想写一个简单的UDP 收发程序,与STM32F429的Mbed OS 进行通信。Linux 是华硕笔记本上Windows WSL (ubuntu)。
Mbed OS上的程序比较简单,是一个UDP echo server。
#include "UDPSocket.h" #include "math.h" #include "arm_math.h" #define ECHO_SERVER_PORT 8000 #define SERVER_ADDR "192.168.31.30" static const char* mbedIp = "192.168.31.106"; //IP static const char* mbedMask = "255.255.255.0"; // Mask static const char* mbedGateway = "192.168.31.1"; //Gateway int main (void) { EthernetInterface eth; eth.set_network(mbedIp,mbedMask,mbedGateway); eth.connect(); printf("\nServer IP Address is %s\n", eth.get_ip_address()); UDPSocket server; server.open(ð); server.bind(eth.get_ip_address(),ECHO_SERVER_PORT); SocketAddress client_addr; char buffer[1024]; while (true) { int n = server.recvfrom(&client_addr, buffer, sizeof(buffer)); server.sendto(client_addr.get_ip_address(),ECHO_SERVER_PORT, buffer, 1024); } }为了屏蔽掉网络编程的细节,方便应用程序的使用。我将网络部分抽象成为一个类UDPClient
UDPClient.h
#ifndef UDPClient_H #define UDPClient_H #include <iostream> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <netdb.h> #include <vector> using namespace std; class UDPClient { private: int sock; int port; struct sockaddr_in addr; public: UDPClient(); bool setup( int port); int sendUDP( const char * address,char *buffer,int size); int recvUDP(char *buffer,int size); bool UDPbind(); void exit(); }; #endifUDPClient.cpp
#include "UDPClient.h" UDPClient::UDPClient(){ port=0; sock=-1; } bool UDPClient::setup(int port) {int reuse = 0; if ( (sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket failed"); return false ; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { perror("setsockopet error\n"); return -1; } memset( &addr, 0, sizeof(addr) ); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY) ; return true; } bool UDPClient::UDPbind() { if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind error:"); return false; } return true; } int UDPClient::sendUDP( const char * address,char *buffer,int size) { addr.sin_addr.s_addr = inet_addr(address); int len=sendto( sock, buffer, 1024, 0, (struct sockaddr *)&addr, sizeof(addr)); return len; } int UDPClient::recvUDP(char *buffer,int size) { int len,recv_num; len = sizeof(addr); addr.sin_addr.s_addr = htonl(INADDR_ANY) ; recv_num = recvfrom(sock, buffer, size, 0, (struct sockaddr *)&addr, (socklen_t *)&len); return recv_num; } void UDPClient::exit() { close( sock ); }clang++ UDPClient.cpp clientTest.cpp -o clientTest
无法收到Mbed 返回的数据
我估计主要是sock 没有bind,接收端口无法确定。所以增加了bind(),并且在send 和recvfrom 之前,切换
addr.sin_addr.s_addr = inet_addr(address);
sendto....
和
addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
recvfrom.....
增加了bind 之后,又发现,Ctr-C 退出后,再次运行会出现
Address already in use
于是在setup中增加了
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { perror("setsockopet error\n"); return -1; }
运行时,很不可靠,以太网运行一段时间,就断掉了。我分析可能是华硕笔记本是1Gbps 网速,而Mbed 是100base T,所以发送不能太快。我现在设置了usleep(4000),也就是4ms。使用任务管理器看网速只有4Mbps不到。这个我不是太明白为啥在window WSL 的linux 下网络为啥如此慢?
我使用的路由器是cisco的。