热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用ErlangUDP做仿真通信

-module(udpserver).-import(crc,[comCrc161]).-export([start0,client1]).%%服务端start()->s

-module(udpserver).

-import(crc,[comCrc16/1]).

-export([start/0,client/1]). %%服务端

start()->

    spawn(fun()->

        server(19997) end).%%开启进程执行server函数 19997

    server(Port)->

        {ok, Socket} = gen_udp:open(Port, [binary, {active, false}]),%%打开udp端口

        io:format("server open socket:~p~n", [Socket]),%%输出内容

        loop(Socket).%%调用loop函数

 

    loop(Socket)->

        inet:setopts(Socket, [{active, once}]),%%启动Socket

        receive

            {udp, Socket, Host, Port, Bin} ->

                io:format("server received:~p~n", [Bin]),

                {Identity, ReceiveBin} = getReceiveBin(Bin),

                io:format("server send:~p~n", [ReceiveBin]),

                gen_udp:send(Socket, Host, Port, ReceiveBin),

                sendSlaveRequest(Socket, Host, Port, Identity, Bin),

                loop(Socket)

        end.

    getReceiveBin(Bin) ->

         Arr = binary_to_list(Bin),

         [_,_,_,Identity,Len,SerialNum|_Others] = Arr,

         case Identity of

            16#02 ->

                 Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],

                Crc = crc:comCrc16(Res),

                {Identity, Res ++ Crc};

           16#06 ->

                Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],

                Crc = crc:comCrc16(Res),

                %%io:format("CRC:~p~n", [Crc]),%%输出内容

                {Identity, Res ++ Crc};

          16#23 ->

               Res = [16#A5,16#5A,16#00,Identity,16#9,SerialNum,16#1],

              Crc = crc:comCrc16(Res),

              {Identity, Res ++ Crc};

          16#07 ->

               DataLen = (Len - 8) * 8,

              <<_First:48,Data:DataLen,_Crc:16>> = Bin,%%从位数组中截取内如,每个字节8位,First截取前6个字节

              %%io:format("Data:~p~n", [Data]),  %%输出内容

              [16#A5,16#5A,16#00,16#07,Len,16#00,16#11,0,0];

          Other ->

              {Identity, Arr}

          end.

 

          sleep(T) ->

                receive

                after T ->

                     ok

                end.

 

%上发下位机请求

sendSlaveRequest(Socket, Host, Port, Identity, Bin) ->

          case Identity of

                16#02 ->

                        sendFeedback(Socket, Host, Port, Bin);

                 Other ->

                      ok

                 end.

 

%发送调剂动作反馈

sendFeedback(Socket, Host, Port, Bin) ->

        sleep(1000),

         ListData = binary_to_list(Bin),

         [_,_,_,Identity,Len,SerialNo|_T] = ListData,

        OtherLen = (Len-16)*8, <<_:48, _:80,Others:OtherLen>> = Bin,

        %% io:format("CrcAndPulse****:~p~n", [Others]),

        [P1, P2, P3, P4] = getPulseCnt(Others, OtherLen),

         %io:format("P1--P4: ~p, ~p, ~p, ~p ~n", [P1, P2, P3, P4]),

         NewSerialNo = if SerialNo >=255 -> 0; true -> SerialNo + 1 end,

         Body = getFeedbackBody(Bin, OtherLen),

         Request = [16#D3, 16#3D, 16#00, 16#85, 16#12, NewSerialNo] ++ Body,

         Crc = crc:comCrc16(Request),

         RequestList = Request ++ Crc,

         %%io:format("sendFeedback****(begin) ~p~n", [RequestList]),

          gen_udp:send(Socket, Host, Port, RequestList),

          io:format("sendFeedback****(end) ~p~n", [RequestList]).

 

getFeedbackBody(Bin, OtherLen)->

    <<_:48, _:4,IsTurnOffBottle_Ap1:1,_:1,IsAdmix_AP1:1,IsPluginBottle_Ap1:1,

    %%注意 按位运算的时候,字节是反序的,高位在前,低位在后 

     _:4,IsTurnOffBottle_Ap2:1,_:1,IsAdmix_AP2:1,IsPluginBottle_Ap2:1,    _:4,IsTurnOffBottle_Ap3:1,_:1,IsAdmix_AP3:1,IsPluginBottle_Ap3:1,

    _:4,IsTurnOffBottle_Ap4:1,_:1,IsAdmix_AP4:1,IsPluginBottle_Ap4:1, BoxTurnDirection:1,_:2,BoxTurnCnt:5, CellTurnCnt:3,_:4,CellTurnDirection:1,

     PushBoxInfo:8, _:5,IsCutoffFilm:1,IsEncBox:1,IsPushFilm:1, _:8,_:8,Others:OtherLen>> = Bin,

    AP1 = calcAdmixpartFeedback(IsPluginBottle_Ap1,IsAdmix_AP1,IsTurnOffBottle_Ap1),

    AP2 = calcAdmixpartFeedback(IsPluginBottle_Ap2,IsAdmix_AP2,IsTurnOffBottle_Ap2),

    AP3 = calcAdmixpartFeedback(IsPluginBottle_Ap3,IsAdmix_AP3,IsTurnOffBottle_Ap3),

    AP4 = calcAdmixpartFeedback(IsPluginBottle_Ap4,IsAdmix_AP4,IsTurnOffBottle_Ap4),

    io:format("***admixpart command:IsTurnOffBottle_Ap4:~p,IsAdmix_AP4:~p,IsPluginBottle_Ap4:~p ~n", [IsTurnOffBottle_Ap4,IsAdmix_AP4,IsPluginBottle_Ap4]),

    BoxRotate = case BoxTurnCnt > 0 of true -> (BoxTurnDirection bsl 7) bor BoxTurnCnt; _ -> 0 end,

    CellRotate = case CellTurnCnt > 0 of true -> (CellTurnDirection bsl 7) bor CellTurnCnt; _ -> 0 end,

    IsPushInBox = PushBoxInfo band 16#01,

    IsPushOutBox = (PushBoxInfo bsr 1) band 16#01,

    BoxOther = PushBoxInfo band 16#3F,

    %%io:format("++++IsPushInBox:~p IsPushOutBox:~p BoxOther:~p ~n", [IsPushInBox,IsPushOutBox,BoxOther]),

    PushBox = (IsPushOutBox bsl 1) bor IsPushInBox,

    Enc = if IsEncBox =:= 1 -> 2#111; true -> 0 end,

    Body = [AP1, AP2, AP3, AP4, BoxRotate, CellRotate, PushBox, Enc, 0, 0].

 

calcAdmixpartFeedback(IsPluginBottle,IsAdmix,IsTurnOffBottle) ->

    B1 = if IsPluginBottle =:= 1 -> 1; true -> 0 end,

    B2 = if IsAdmix =:= 1 -> 2#111; true -> 0 end,

    B3 = if IsTurnOffBottle =:= 1 -> 1; true -> 0 end,

    (B3 bsl 4) bor (B2 bsl 1) bor B1. getPulseCnt(Crc, 16)-> [0,0,0,0];

 

getPulseCnt(Crc, 48)->

    [Crc bsr 16,0,0,0];

getPulseCnt(Crc, 80)->

    [Crc bsr 48,(Crc bsr 16) band 16#FFFFFFFF,0,0];

getPulseCnt(Crc, 112)->

    [Crc bsr 80, (Crc bsr 48) band 16#FFFFFFFF, (Crc bsr 16) band 16#FFFFFFFF,0];

getPulseCnt(Crc, 144)->

    [Crc bsr 112, (Crc bsr 80) band 16#FFFFFFFF, (Crc bsr 48) band 16#FFFFFFFF, (Crc bsr 16) band 16#FFFFFFFF]. %%客户端

 

client(N) ->

    {Res, Socket} = gen_udp:open(0, [binary]),

     io:format("client opened socket:~p ~p~n", [Res, Socket]),

    ok = gen_udp:send(Socket, "localhost", 4000, N),

    Value = receive

         {udp, Socket, _, _, Bin} ->

            io:format("client received:~p~n", [Bin])

         after

            2000 -> 0

         end,

    gen_udp:close(Socket),

    Value.

 

CRC模块代码:

-module(crc).

-export([comCrc16/1]).

for(Max, Max, F, R)-> F(R);

for(I, Max, F, R)->for(I + 1, Max, F, F(R)).

transform(R1) ->

    for(0, 7, fun(R)->

        begin

            Flag = R band 16#1,

            if Flag =/= 0 -> (R bsr 1) bxor 16#A001;

                true -> R bsr 1

            end

        end

    end, R1).

getCrcValue([H|T], R)->

    Ch = H band 16#FF,

    R1 = R bxor Ch,

    R2 = transform(R1),

    getCrcValue(T, R2);

getCrcValue([], R) ->

    R.

comCrc16(Data) ->

    Crc = getCrcValue(Data, 16#FFFF),

    First = Crc band 16#FF,

    Secend = Crc bsr 8,

     [First, Secend].


推荐阅读
  • 本文深入探讨了 Spring Cloud 微服务架构中 Gateway 组件的应用,详细介绍了其在实现高效请求路由与过滤方面的关键作用。文章首先从基本配置入手,逐步讲解了如何通过静态路由和动态路由实现灵活的服务访问控制。此外,还特别介绍了如何配置 Gateway 以自动从 Nacos 服务注册中心拉取服务列表,进一步提升系统的可维护性和扩展性。 ... [详细]
  • 深入解析Tomcat:开发者的实用指南
    深入解析Tomcat:开发者的实用指南 ... [详细]
  • 如何在Java中高效构建WebService
    本文介绍了如何利用XFire框架在Java中高效构建WebService。XFire是一个轻量级、高性能的Java SOAP框架,能够简化WebService的开发流程。通过结合MyEclipse集成开发环境,开发者可以更便捷地进行项目配置和代码编写,从而提高开发效率。此外,文章还详细探讨了XFire的关键特性和最佳实践,为读者提供了实用的参考。 ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • Liferay Portal 中 AutoEscape 构造函数的应用与实例代码解析 ... [详细]
  • 在Spring框架中,基于Schema的异常通知与环绕通知的实现方法具有重要的实践价值。首先,对于异常通知,需要创建一个实现ThrowsAdvice接口的通知类。尽管ThrowsAdvice接口本身不包含任何方法,但开发者需自定义方法来处理异常情况。此外,环绕通知则通过实现MethodInterceptor接口来实现,允许在方法调用前后执行特定逻辑,从而增强功能或进行必要的控制。这两种通知机制的结合使用,能够有效提升应用程序的健壮性和灵活性。 ... [详细]
  • 本文深入探讨了Spring Cloud Eureka在企业级应用中的高级使用场景及优化策略。首先,介绍了Eureka的安全配置,确保服务注册与发现过程的安全性。接着,分析了Eureka的健康检查机制,提高系统的稳定性和可靠性。随后,详细讨论了Eureka的各项参数调优技巧,以提升性能和响应速度。最后,阐述了如何实现Eureka的高可用性部署,保障服务的连续性和可用性。通过这些内容,开发者可以更好地理解和运用Eureka,提升微服务架构的整体效能。 ... [详细]
  • 提升工作效率:掌握这些技巧,IDEA 使用效率翻倍 | IDEA 高效操作指南
    提升工作效率:掌握这些技巧,IDEA 使用效率翻倍 | IDEA 高效操作指南 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • 第五章详细探讨了 Red Hat Enterprise Linux 6 中的 Ext3 文件系统。5.1 节介绍了如何创建 Ext3 文件系统,包括必要的命令和步骤,以及在实际操作中可能遇到的问题和解决方案。此外,还涵盖了 Ext3 文件系统的性能优化和维护技巧,为用户提供全面的操作指南。 ... [详细]
  • PyQt5 QTextEdit:深入解析Python中多功能GUI库的应用与实现
    本文详细探讨了 PyQt5 中 QTextEdit 组件在 Python 多功能 GUI 库中的应用与实现。PyQt5 是 Qt 框架的 Python 绑定,提供了超过 620 个类和 6000 个函数及方法,广泛应用于跨平台应用程序开发。QTextEdit 作为其中的重要组件,支持丰富的文本编辑功能,如富文本格式、文本高亮和自定义样式等。PyQt5 的流行性不仅在于其强大的功能,还在于其易用性和灵活性,使其成为开发复杂用户界面的理想选择。 ... [详细]
  • 本课程详细解析了Spring AOP的核心概念及其增强机制,涵盖前置增强、后置增强和环绕增强等类型。通过具体示例,深入探讨了如何在实际开发中有效运用这些增强技术,以提升代码的模块化和可维护性。此外,还介绍了Spring AOP在异常处理和性能监控等场景中的应用,帮助开发者更好地理解和掌握这一强大工具。 ... [详细]
  • 在启用分层编译的情况下,即时编译器(JIT)的触发条件涉及多个因素,包括方法调用频率、代码复杂度和运行时性能数据。本文将详细解析这些条件,并探讨分层编译如何优化JVM的执行效率。 ... [详细]
  • 在Python 3环境中,当无法连接互联网时,可以通过下载离线模块包来实现模块的安装。具体步骤包括:首先从PyPI网站下载所需的模块包,然后将其传输到目标环境,并使用`pip install`命令进行本地安装。此方法不仅适用于单个模块,还支持依赖项的批量安装,确保开发环境的完整性和一致性。 ... [详细]
  • 本文探讨了将PEBuilder转换为DIBooter.sh的方法,重点介绍了如何将DI工具集成到启动层,实现离线镜像引导安装。通过使用DD命令替代传统的grub-install工具,实现了GRUB的离线安装。此外,还详细解析了bootice工具的工作原理及其在该过程中的应用,确保系统在无网络环境下也能顺利引导和安装。 ... [详细]
author-avatar
莪乜子12
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有