热门标签 | 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].


推荐阅读
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了如何找到并终止在8080端口上运行的进程的方法,通过使用终端命令lsof -i :8080可以获取在该端口上运行的所有进程的输出,并使用kill命令终止指定进程的运行。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了如何使用iptables添加非对称的NAT规则段,以实现内网穿透和端口转发的功能。通过查阅相关文章,得出了解决方案,即当匹配的端口在映射端口的区间内时,可以成功进行端口转发。详细的操作步骤和命令示例也在文章中给出。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • 修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法
    本文介绍了修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法。首先解释了UEFI的概念和作用,然后提供了两种解决方法。第一种方法是在bios界面中将Boot Mode设置为Legacy Support,Boot Priority设置为Legacy First,并关闭UEFI。第二种方法是使用U盘启动盘进入PE系统,运行磁盘分区工具DiskGenius,将硬盘的分区表设置为gpt格式,并留出288MB的内存。最后,通过运行界面输入命令cmd来完成设置。 ... [详细]
author-avatar
112473228
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有