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

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

最近一直在学习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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  
#include 

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"<

程序编译

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

你可能感兴趣的:(mbed,linux,UDP)