基于UDP的网口设备通讯(一)

题记

最近做了一个小项目,基于UDP协议的上位机与下位机通讯项目。项目不算大,代码量(算上UI布局)也就700来行。但是感觉学到的东西不少。开一篇记录,记录,记录一下。

使用到的库

其实网口通讯方式的上位机制作简单,不像是USB通讯需要很麻烦的引用第三方库。UDP通讯只需要使用.Net自带的Sockets库就可以了。
我使用的是.Send和.Receive方式实现发送和接收数据

功能实现

 //设置本机IP及端口(用于信息接收)
IPEndPoint localIpep = new IPEndPoint(IPAddress.Parse("192.168.123.1"), 8080);
//设计本机IP及端口(用于命令下发)
IPEndPoint localIpep2 = new IPEndPoint(IPAddress.Parse("192.168.123.1"), 1100);
//定义发送到的IP地址和端口号
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse("192.168.123.100"), 1080);

注:此处定义了两组IP地址和三个端口

至于为什么要在本机开两个不同的端口:

主要是我的设备我想要做成实时不间断的接收下位机返回的消息,而又要实现设备的启停。尝试过如果只用一个相同的端口,在启停命令发送完之后使用.Close()的方法使上位机放开端口。但是不知道是什么原因,可能放开的比较慢,有延时感,如果紧接着读取数据就会抛出IP重复定义的异常。所以干脆直接定义了两个端口。

开始发送接收指令:

实例化用以接收发送

//用以发送消息
private UdpClient udpcSend;
//用以接收消息
 private UdpClient udpcRecv;
 //发送指令
public void SendMessage()
        {
        	//此句是获取UI界面的参数的方法,感兴趣的大佬可以使用WPF的绑定方法
            GetBytes();
            //将数据按照协议方式打包
            byte[] sendMessage = Pack();
            //将数据发送(数据源,长度,地址)
            udpcSend.Send(sendMessage, sendMessage.Length, remoteIpep);
        }
private void ReceiveMessage()
        {
        	//侦听所有网络接口上活动的IP地址
            IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
            //接收数据,前面bytRecv可以是一个缓存区
            bytRecv = udpcRecv.Receive(ref remoteIpep);
        }

至此其实简单的UDP数据接收和发送的功能就已经完成了。但是发送和接收都要按照协议格式呀。发送还算是简单,底层的人告诉发送格式,UDP发送自动添加包头包尾校验位之类的。麻烦在接收。

接收数据校验:

听着名字高大上,但是我更喜欢通俗的解释:其实就是收到的数据包中有很多没用的东西(比如包头,包尾,校验,地址等等我不是专门做互联网的所以对这些也没有深入研究。感兴趣的大佬可自行去了解)。然后我的下位机一个包还是分成四份发的。总之:我的任务就是拿到包头和包尾以及之间的关键数据。

获取需要的数据:

说实话,这个算法写的是真的蠢,希望能有大佬指点一二:

//校验包头所包含的数据
byte[] headCheck = { ******* /*意思了一下校验没正经写*/ };
//校验包尾所包含的数据
byte[] tailCheck = { ******* /*意思了一下校验没正经写*/};

现在要做的就是识别包头开始接收数据,将下位机发来的数据拼接起来。直到收到包尾。

小弟的想法是,在外部定义一个容器,当收到包头时先将这一包加入缓存区,接收下一包时候开始查找包尾,没有包尾的话就和前面的缓存区拼接直到收到包尾结束。当完整的一包接收完毕后将缓存区清空以查找下一组数据的包头。

//烂算法
private void ReceiveMessage()
        {
            IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);

            //读数据并验证数据
            while (true)
            {
                try
                {
                    //返回远程机发回的信息
                    bytRecv = udpcRecv.Receive(ref remoteIpep);

                    //如果缓存区为空找头tempData是定义的缓存区
                    if (tempData.Count == 0)
                    {
                        //进行八次校验
                        for (int i = 0; i < headCheck.Length; i++)
                        {
                            if (headCheck[i] != bytRecv[i])
                            {
                                break;
                            }
                            //如果八次全部相同则为所需的包头
                            if (i == 7)
                            {
                                //将包头加入到数据区
                                tempData.AddRange(bytRecv);
                            }
                        }
                    }
                    else
                    {
                        //缓存区不空找尾
                        for (int i = 0; i < tailCheck.Length; i++)
                        {
                            //如果没有找到检验尾,将数据插入缓存区
                            if (tailCheck[i] != bytRecv[bytRecv.Length - 8 + i])
                            {
                                //将此包与前面的包拼接
                                tempData.AddRange(bytRecv);
                                break;
                            }
                            if (i == 7)
                            {
                                //如果找到了校验尾:将数据插入缓存区后开始数据处理
                                tempData.AddRange(bytRecv);
                                //中间有一些数据处理的内容删掉了
                                tempData.Clear();
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    break;
                }
            }
        }

后记

自知码龄比较短,写的程序比较蠢。不敢误人子弟,所以这只是记录篇。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zynq是一种基于Xilinx的可编程逻辑器件(FPGA)和ARM处理器(Cortex-A9)集成在一起的芯片。它提供了一种灵活且高性能的解决方案,可用于嵌入式系统的设计和开发。 在Zynq芯片中,UDP协议是一种基于IP协议的传输层协议,用于在络中进行无连接的数据传输。UDP协议通过UDP套接字实现数据的收发。 要在Zynq上实现UDP口收发,首先需要配置FPGA的硬件设计。可以使用Xilinx提供的Vivado开发环境进行设计,选择合适的IP核来实现UDP收发功能。然后,将设计完成的BIT文件加载到Zynq芯片上。 之后,通过在ARM处理器上运行的操作系统(比如Linux)中的络配置,将口与指定的IP地址和端口进行绑定。可以使用Linux提供的命令行工具(如ifconfig和route)进行络配置。 在应用程序中,可以使用任何支持UDP协议的编程语言来进行UDP数据的收发操作。例如,在C语言中,可以使用socket函数库来创建UDP套接字,并使用sendto和recvfrom函数来发送和接收UDP数据包。 需要注意的是,使用UDP进行数据传输时,由于UDP是无连接的,因此没有对数据的完整性和可靠性进行验证。这意味着在收发数据时,需要特别注意丢包和数据错误的情况。 总之,通过配置FPGA的硬件设计,配置络参数,并在应用程序中使用适当的函数库,我们可以在Zynq芯片上实现UDP口收发功能。这样,我们可以在络中快速传输数据,并实现实时应用程序的通信和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值