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

22 篇文章 6 订阅

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

最近一直在学习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(&eth);
    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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值