数据处理中心并不知道各个数据产生终端的具体位置(IP地址区分),因此和特定终端在建立命令通道和数据流通道之前必须事先捕获其IP。
基于UDP的特性,终端的发现使用UDP协议实现。
(1)UDP特性:
UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当
它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。UDP不存在粘包的现象,它是有报文边界的,接收方调用一次接收保证只会收到一个udp包(待接收的包长度如果超过你提供的缓冲区长度,那么底层会简单的丢弃这个包,导致你收不到数据,理论上包含报头在内的数据报的最大长度为65535字节)。
(2)终端发现机制:
使用UDP的广播特性,每个数据终端做子网广播。数据处理中心在特定端口接收广播,获取终端IP并使用。因为数据处理中心只是实现接入端的发现,因此无需回复响应报文给检测到的数据终端。
(3)设计概要:
因为UDP传输是对等的,不存在服务端和客户端的区别,但是作为终端发现类库的实现,应给类库的使用者提供合理,人性的调用接口(构造函数,开始监听,停止监听,释放资源,注册事件)。
类库命名为UdpServer,包含监听类,事件参数类,事件产生类,方法调用类。其中事件参数类中包含2个属性,一个是Message(string),一个是EndPoint( System.Net.EndPoint)。数据终端广播来的自身信息,比如IP,名称,固件版本等传递给Message。EndPoint包含IP和Port。因终端广播的数据包含其自身IP,其实EndPoint并没有使用。
(4)类关系图如下:
(5)异步接收代码
BaseServer.cs中:
internal
void
Start()
{
if ( this ._serverState == 0 )
{
this ._serverState = 1 ;
this ._listenThread = new Thread( new ThreadStart( this .OnListen));
this ._listenThread.IsBackground = true ;
this ._listenThread.Start();
}
}
{
if ( this ._serverState == 0 )
{
this ._serverState = 1 ;
this ._listenThread = new Thread( new ThreadStart( this .OnListen));
this ._listenThread.IsBackground = true ;
this ._listenThread.Start();
}
}
MyUdpListener.cs中:
private
void
OnBeginReceiveFrom(IAsyncResult ar)
{
try
{
ReceiveState asyncState = ar.AsyncState as ReceiveState;
EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0 );
if (( this .mUdpClient != null ) && ( this .mUdpClient.Client != null ))
{
this .mUdpClient.Client.EndReceiveFrom(ar, ref endPoint);
string message = Encoding.UTF8.GetString(asyncState.Buffer).Replace( " \0 " , "" );
base .RaiseEvent( new NewMessage(endPoint, message));
asyncState.SetEvent();
}
}
catch
{
}
}
protected internal override void OnProcessRequest()
{
EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0 );
AutoResetEvent evt = new AutoResetEvent( false );
ReceiveState state = new ReceiveState(evt);
try
{
this .mUdpClient.Client.BeginReceiveFrom(state.Buffer, 0 , 0x400 , SocketFlags.None, ref remoteEP, new AsyncCallback( this .OnBeginReceiveFrom), state);
evt.WaitOne();
}
catch
{
}
Thread.Sleep( 10 );
}
{
try
{
ReceiveState asyncState = ar.AsyncState as ReceiveState;
EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0 );
if (( this .mUdpClient != null ) && ( this .mUdpClient.Client != null ))
{
this .mUdpClient.Client.EndReceiveFrom(ar, ref endPoint);
string message = Encoding.UTF8.GetString(asyncState.Buffer).Replace( " \0 " , "" );
base .RaiseEvent( new NewMessage(endPoint, message));
asyncState.SetEvent();
}
}
catch
{
}
}
protected internal override void OnProcessRequest()
{
EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0 );
AutoResetEvent evt = new AutoResetEvent( false );
ReceiveState state = new ReceiveState(evt);
try
{
this .mUdpClient.Client.BeginReceiveFrom(state.Buffer, 0 , 0x400 , SocketFlags.None, ref remoteEP, new AsyncCallback( this .OnBeginReceiveFrom), state);
evt.WaitOne();
}
catch
{
}
Thread.Sleep( 10 );
}