(写于OHSCEV0.1.23) 面对以太网我们需要使用TCP/UDP进行通信,TCP/UDP在世界互联网范围内被广泛使用,同时它也被广泛应用于物联网、工业网等控制通信网上。不过区别于互联网上的极致追求高并发高效率普通应用,更偏重的是与浏览器/应用客户端交互。我们的应用场景是与控制设备交互,更注重准确性、可靠性、稳定性。也正是因此目前纯粹的基于TCP/UDP的NCS控制系统在大型系统基本是不可行的,但是事情不是一成不变的,总要动态的去看问题。随着网络技术的发展越来越成熟,我们越来越多的要去接触它,在控制领域对它的使用和在普通应用中对它的使用是有很多不同的,OHSCE为您平衡了它们。另外个人认为复合型的控制系统是相对科学的。 一、OHSCE中的TCP/UDP函数族。 主要分为封装函数和基础函数,绝大多数的需求使用封装函数即可完成,但是OHSCE也提供给您了操作更接近底层的基础函数库。 封装函数Ohsce_eng_socket_X。 首先在建立一个SERVER/CLIENT之前需要先构建一个链接预备资源,其实此资源在OHSCE中就是一个数组结构,存储了这个资源在调用和运行中需要的各个数据。构建一个链接预备资源非常简单,只需要一个函数就可以解决。 CLIENT: Ohsce_eng_socket_client SERVER: Ohsce_eng_socket_server DO: Ohsce_eng_socket_send Ohsce_eng_socket_recv Ohsce_eng_socket_server_runtcp Ohsce_eng_socket_server_runudp Ohsce_eng_socket_server_close 二、我们先构建一个CLIENT: TCP: Ohsce_eng_socket_client($ohsceclient,'tcp',7628,'127.0.0.1'); //创建一个TCP客户端资源并连接127.0.0.1:7626 UDP: Ohsce_eng_socket_client($ohsceclient,'udp',7628,'127.0.0.1'); //创建一个UDP客户端资源并绑定127.0.0.1:7628 这样一个变量名为$ohsceclient的链接资源就创建完成了,是不是很简单,实际上Ohsce_eng_socket_client函数还可以很强大,它有很多输入量都被OHSCE自动为您填充了。Ohsce_eng_socket_client(&$OhsceClient,$protocol,$port,$ip=null,$AF='ipv4',$sync=true,$mode='defalut') 函数支持您创建不同协议的客户端模式链接资源,支持IPV4和IPV6(默认为IPV4),支持同步和异步,和多种预设定模式(默认为default) 三、再构建相应的SERVER 其实TCP是有链接的而UDP是无链接的,而所谓UDPSERVER资源只是在告诉OHSCE应该以SERVER姿态去运行这个资源。 Ohsce_eng_socket_server函数能够帮助你轻松的创建一个SERVER预备资源。但是在创建这个资源之前我们还需要两件件事情要做。 第一件是为SERVER资源预备回调函数。其中TCP需要两个回调函数,UDP需要一个回调函数。 TCP回调函数分别为新客户端到达函数(callbackaccept)和旧客户端回调函数(callback),新客户端到达回调函数其实就是TCP握手后第一个信息。因为这个信息很多时候是一个硬件登陆信息,如果您的设备没有登陆动作那您可以不准备此函数。旧客户端回调函数是每次有数据到达都会调用的一个函数。 举个栗子: function example(&$socket,$buf,$len,$zv){ //收到数据时的回调函数 echo $buf; Ohsce_socketwrite($socket,'hi '.$buf); return true; } function exampleaccept(&$socket,$ip,$port,$zv){ //新客户端到访时的回调函数 Ohsce_socketwrite($socket,'Welcome'.$ip.':'.$port); return true; } 其中example函数会被传入本次连接的socket资源的指针,$buf为数据内容,$len为数据长度,$zv为OHSCE固定结构体(数组形式)。 <?php $zv=array("clients"=>&$oibc_clients,"ip"=>&$oibc_clients_id_ip,"id"=>&$oibc_clients_id); 这个数组会由OHSCE自动生成并传递给您。其中clients是客户端列表(包含一个占位符,这个您不用管),ip是客户端ip表,id是客户端表备份便于您回滚。您可以操作它管理各数据,包含手动进行心跳操作(如果您的需求需要)。 另一个函数exampleaccept(&$socket,$ip,$port,$zv)是在新客户端到访时被调用的。 第二件事是构建常驻函数 常驻函数是每次循环都会被执行的函数,如果您不需要完全可以直接写成。 <?php function fap(&$zv){ return true; } 传入的参数只有结构体数组$zv.此函数很多情况下是用于手动发送心跳的(如果需要)。 好了俩事都办完了我们现在可以构建SERVER了。 <?php Ohsce_eng_socket_server($ohsceserver,'tcp',7626,'127.0.0.1',array('callback'=>'example','accept'=>'exampleaccept','fap'=>'fap'),'example'); 其中$ohsceserver就是我们构建好的server。后面依次是tcp协议,7627端口,回调函数组(只需要传入函数名即可),最后一个回调函数名是0.1.X兼容写法。其实OHSCE的SERVER远比演示强大,可以参考文档。 四、让SERVER运转起来并使用CLIENT去连接 在OHSCE中运转一个SERVER是非常容易的事情,对于基础的需求只需要一个函数你的SERVER就被激活并开始运转了。 Ohsce_eng_socket_server_runtcp($ohsceserver); //开始运行 这时候,一个服务端口是7627占用IP是127.0.0.1,回调函数是example()欢迎函数exampleaccept(),并且每各循环都会运行一个fap()常驻函数的TCPSERVER就启动啦。 现在我们可以CLIENT文件添加读写操作。 Ohsce_socketsend($ohsceclient['socket'],'hello'); //发送数据 echo Ohsce_socketread($ohsceclient['socket'],1024)[1]; //收取回复数据 运行CLIENT文件,其实客户端资源在创建时默认就进行了连接(至少目前版本是这样设计的),所以直接就可以进行读写操作了。 六、有关UDP UDP和TCP的区别是UDP是无连接的通信协议而TCP是有链接的通信协议,所以理论上TCP比UDP更可靠一些。但是在本机或可靠的设备内网,其可靠性方面的差异并不大但毕竟UDP风险还是略高一些,但是对于非关键位置的查询型设备设计上下位机通信是还是可以考虑此协议。所以还是能见到UDP控制设备的,虽然其很少见,笔者就遇到过,我们举一个UDP的使用例子。 UDPSERVER ini_set('memory_limit',"88M");//重置php可以使用的内存大小为88M set_time_limit(0); ob_implicit_flush(1); include('loadohsce.php'); $trya='ohsce_server_Example '; function example(&$socket,$buf,$from,$port,$zv){ //收到数据时的回调函数 global $trya; echo $buf; Ohsce_socketsend($socket,$trya.'hi '.$buf,0,0,$from,$port); return true; } function fap(&$zv){ return true; } Ohsce_eng_socket_server($ohsceserver,'udp',7626,'127.0.0.1',array('callback'=>'example','fap'=>'fap'));//创建一个UDP服务端资源 绑定127.0.0.1:7626 并传入回调函数 @Ohsce_eng_socket_server_runudp($ohsceserver); //开始运行 其实UDP没有SERVER概念,所谓SERVER只是我们的逻辑SERVER罢了。 UDPCLIENT ini_set('memory_limit',"88M");//重置php可以使用的内存大小为64M set_time_limit(0); ob_implicit_flush(1); include('loadohsce.php'); Ohsce_eng_socket_client($ohsceclient,'udp',7628); //创建一个UDP客户端资源并绑定7628 Ohsce_socketsend($ohsceclient['socket'],'hello',0,0,'127.0.0.1',7626); Ohsce_socketrecvfrom($ohsceclient['socket'],$buf,0,0,$from,$port); //收取回复数据 echo $buf.'|'.$from.':'.$port; sleep(30); 同样,这只不过是逻辑客户端罢了。 显而易见,UDP带来了高效、简单、迅捷的优点,但是别忘了它的硬伤它并不确保数据可靠到达和到达顺序。不过一般情况下,UDP设备均有应答机制。 七、科学的拆分你的逻辑到回调函数和常驻函数中去。