使用Erlang UDP做仿真通信

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

时间: 2024-12-23 03:32:35

使用Erlang UDP做仿真通信的相关文章

JAVA基础知识之网络编程——-基于UDP协议的通信例子

UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramSocket类的receive和send方法即可,但消息需要通过一个特定的类封装(DatagramPacket) 下面是一个基于UDP协议的通信的例子, 服务器端, 1 package udp; 2 3 import java.io.IOException; 4 import java.net.Dat

[java]基于UDP的Socket通信Demo

java课编程作业:在老师给的demo的基础上实现客户端发送数据到服务器端,服务器端接受客户端后进行数据广播. 整体功能类似于聊天室,代码部分不是太难,但是在本机测试的时候出现这样的问题: 服务端通过将每一个Socket客户端的IP存入Set集合,每次接受到数据后都向当前所有的IP转发.但是本机演示的时候所有开的ChatClient客户端都是同一IP,怎么测试呢? 解决办法就是本机测试时候服务端向多个不同的端口转发就好了,这样跑起来的客户端是在不同端口上进行监听的(只是为了实现广播,实际应用下还

uip UDP客户端模式通信移植,本地端口可以随机

目前移植了UDP客户端模式,测试使用广播地址. //udp_client.c /************************************************************************************************************* * 文件名: udp_client.c * 功能: uIP UDP客户端相关函数 * 作者: [email protected] * 创建时间: 2014-06-06 * 最后修改时间: 2014-0

Java 网络编程(六) 使用无连接的数据报(UDP)进行通信

连接地址:http://www.cnblogs.com/mengdd/archive/2013/03/10/2952673.html 使用无连接的数据报(UDP)进行通信 什么是Datagram? 数据报是网上传输的独立数据包,数据报是否能正确地到达目的地,到达的时间,顺序,内容的正确性均没有保障. Java中使用Datagram与DatagramPacket类. DatagramSocket类利用UDP协议来实现客户与服务器的Socket. send()发送数据报. receive()接收数据

用udp实现广播通信

特点: 1.数据传输不用建立连接,所以不可靠(符合udp协议的特点) 2.数据的发送是面向整个子网的,任何一台在子网内的计算机都可以接收到相同的数据: 3.广播用于udp和原始IP,不能用于TCP 用途: 1.定位本地子网内的主机 前提是已知该主机位于本地子网,但是不知到他的单播地址.例如通过广播向所有子网内的主机的某端口发送数据报,如果主机有进程在该端口等待接收数据并回射数据,那么在recvfrom中会得到该主机的单播地址 2.减少分组流通 例如,多个客户主机与一个服务器主机通信的局域网中,广

27.Socket,TCP,UDP,HTTP基本通信原理

Socket,TCP,UDP,HTTP基本通信原理(摘自百度): TCP.UDP,HTTP 底层通信都是通过 socket 套接字实现 网络上不同的计算机,也可以通信,那么就得使用网络套接字(socket). socket就是在不同计算机之间进行通信的一个抽象. 他工作于TCP/IP协议中应用层和传输层之间的一个抽象  如图所示: 1.Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层.从设计模式的角度看来,Socket其实就是一个门面模式,它把

recv原理、高阶版黏包解决方案、基于UDP的socket通信

recv原理.高阶版黏包解决方案.基于UDP的socket通信 recv原理 源码解释: Receive up to buffersize bytes from the socket. 接收来自socket缓冲区的字节数据, For the optional flags argument, see the Unix manual. 对于这些设置的参数,可以查看Unix手册. When no data is available, block untilat least one byte is av

一个简单的UDP协议的通信

Server import socket #引入socket模块 #建立一个UDP的服务端 udpServer = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #127.0.0.1 - 127.255.255.254 都属于访问本地 但是都是用 127.0.0.1 udpServer.bind(("10.0.144.160",8244)) #将server绑定一个ip和端口号,以便客户端访问 while True: print(&qu

linux系统UDP的socket通信编程3

我刚开始接触linux下的socket编程,边抄边理解udp socket编程,我的疑问是server不指定IP地址,client的目标IP地址是127.0.0.1,这样就可以通信吗?在同一主机下是不是不能测试?如果server默认绑定本机的IP 地址,那么开启server后,在浏览器中输入127.0.0.1:(相应端口) 也可以得到数据?我的程序如下,没有跑起来,其实我觉得我不会测试,不知道本质所以会有细节漏掉.(使用的系统是ubuntu 11.10 ,编译器GCC ,分别在同一主机下的两个终