Linux 和Mbed OS UDP 通信(C++)

    xiaoxiao2022-07-06  198

    这几乎是一个非常菜鸟的程序,但是搞了我半天。

    最近一直在学习linux C++程序设计,于是想写一个简单的UDP 收发程序,与STM32F429的Mbed OS 进行通信。Linux 是华硕笔记本上Windows WSL (ubuntu)。

      Mbed OS 代码

    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); } }

    Linux 上的代码

    为了屏蔽掉网络编程的细节,方便应用程序的使用。我将网络部分抽象成为一个类UDPClient

    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(); }; #endif

    UDPClient.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 ); }

    应用程序

    #include "UDPClient.h" #define MY_PORT 8000 int main( void ) { int i; char buffer[1024]; UDPClient client; client.setup(MY_PORT); client.UDPbind(); cout<<"UDP Test"<<endl; while(true) { if (client.sendUDP("192.168.31.106", buffer, 1024) < 0 ) { perror( "sendto:" ); break; } if(client.recvUDP(buffer, 1024) <0) { perror( "recvfrom:" ); break; } usleep(4000); } client.exit(); }

    程序编译

    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的。

    最新回复(0)