怎样使用php实现tcp/udp通讯1.在socket_bind的时候ip地址不能真回环地址如127.0.0.1
2.server.php后台跑起来的时候nohup php server.php/var/tmp/a.log 21
一: udp 方式
1) server.php
?php//error_reporting( E_ALL );set_time_limit( 0 );ob_implicit_flush();$socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );if ( $socket === false ) {echo "socket_create() failed:reason:" . socket_strerror( socket_last_error() ) . "\n";}$ok = socket_bind( $socket, '202.85.218.133', 11109 );if ( $ok === false ) {echo "socket_bind() failed:reason:" . socket_strerror( socket_last_error( $socket ) );}while ( true ) {$from = "";$port = 0;socket_recvfrom( $socket, $buf,1024, 0, $from, $port );echo $buf;usleep( 1000 );}?
2) client.php
?php$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);$msg = 'hello';$len = strlen($msg);socket_sendto($sock, $msg, $len, 0, '202.85.218.133', 11109);socket_close($sock);?
二: TCP 方式
1)server.php
?php//error_reporting( E_ALL );set_time_limit( 0 );ob_implicit_flush();$socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );socket_bind( $socket, '192.168.2.143', 11109 );socket_listen($socket);$acpt=socket_accept($socket);echo "Acpt!\n";while ( $acpt ) {$words=fgets(STDIN);socket_write($acpt,$words);$hear=socket_read($acpt,1024);echo $hear;if("bye\r\n"==$hear){socket_shutdown($acpt);break;}usleep( 1000 );}socket_close($socket)?
2) client.php
?php$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);$con=socket_connect($socket,'192.168.2.143',11109);if(!$con){socket_close($socket);exit;}echo "Link\n";while($con){$hear=socket_read($socket,1024);echo $hear;$words=fgets(STDIN);socket_write($socket,$words);if($words=="bye\r\n"){break;}}socket_shutdown($socket);socket_close($sock);?
如何连续接收udp报文UDP包UDP报头由4个域组成,其中每个域各占用2个字节,具体如下:源端口号目标端口号数据报长度校验值 UDP协议使用端口号为不同的应用保留其各自的数据传输通道 。UDP和TCP协议正是采用这一机制实现对同一时刻内多项应用同时发送和接收数据的支持 。数据发送一方(可以是客户端或服务器端)将UDP数据报通过源端口发送出去,而数据接收一方则通过目标端口接收数据 。有的网络应用只能使用预先为其预留或注册的静态端口;而另外一些网络应用则可以使用未被注册的动态端口 。因为UDP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535 。一般来说,大于49151的端口号都代表动态端口 。TCP包每个tcp都包含源端口号和目标端口号,加上ip头中的源ip和目的ip,唯一确定一个tcp连接 。序号用来标识从tcp发端向tcp收端发送的数据字节流,它表示在这个报文段中的第一个数据字节 。序号字段包含由这个主机选择的该连接的初始序号isn(Initial Sequence Number) 。该主机要发送数据的第一个字节,序号为isn 1,因为syn占用了一个序号 。IP包IPV4报头有12个必需的字段和可选IP选项字段 , 位于要发送的数据之前 。如果使用IP层已有的库或其他组件 , 一般不必考虑报头中的大多数字段,但程序代码需要提供源端和目的端地址 。1、版本(4比特)IP协议版本已经经过多次修订,1981年的RFC0791描述了IPV4 , RCF2460中介绍了IPV6 。2、报头长度(4比特)报头长度是报头数据的长度,以4字节表示,也就是以32字节为单位 。报头长度是可变的 。必需的字段使用20字节(报头长度为5 , IP选项字段最多有40个附加字节(报头长度为15) 。3、服务类型(8比特)该字段给出发送进程建议路由器如何处理报片的方法 。可选择最大可靠性、最小延迟、最大吞吐量和最小开销 。路由器可以忽略这部分 。4、数据报长度(16比特)该字段是报头长度和数据字节的总和,以字节为单位 。最大长度为65535字节 。5、标识符(16比特)原是数据的主机为数据报分配一个唯一的数据报标识符 。在数据报传向目的地址时,如果路由器将数据报分为报片,那么每个报片都有相同的数据标识符 。6、标志(3比特)标志字段中有2为与报片有关 。位0:未用 。位1:不是报片 。如果这位是1,则路由器就不会把数据报分片 。路由器会尽可能把数据报传给可一次接收整个数据报的网络;否则,路由器会放弃数据报,并返回 差错报文,表示目的地址不可达 。IP标准要求主机可以接收576字节以内的数据报,因此,如果想把数据报传给未知的主机,并想确认数据报没有因为大小的原 因而被放弃,那么就使用少于或等于576字节的数据 。位2:更多的报片 。如果该位为1,则数据报是一个报片,但不是该分片数据报的最后一个报片;如果该位为0 , 则数据报没有分片,或者是最后一个报片 。7、报片偏移(13比特)该字段标识报片在分片数据报中的位置 。其值以8字节为单位,最大为8191字节,对应65528字节的偏移 。例如,将要发送的1024字节分为576和424字节两个报片 。首片的偏移是0 , 第二片的偏移是72(因为72×8=576) 。8、生存时间(8比特)如果数据报在合理时间内没有到达目的地 , 则网络就会放弃它 。生存时间字段确定放弃数据报的时间 。生存时间表示数据报剩余的时间,每个路由器都会将其值减一,或递减需要数理和传递数据报的时间 。实际上,路由器处理和传递数据报的时间一般都小于1S,因此该值没有测量时间 , 而是测量路由器之间跳跃次数或网段的个数 。发送数据报的计算机设置初始生存时间 。9、协议(8比特)该字段指定数据报的数据部分所使用的协议,因此IP层知道将接收到的数据报传向何处 。TCP协议为6,UDP协议为17 。10、报头检验和(16比特)该字端使数据报的接收方只需要检验IP报头中的错误,而不校验数据区的内容或报文 。校验和由报头中的数值计算而得,报头校验和假设为0 , 以太网帧和TCP报文段以及UDP数据报中的可选项都需要进行报文检错 。11、源IP地址(32比特)表示数据报的发送方 。12、目的IP地址(32比特)表示数据报的目的地 。
如何 监听,接收 所有UDP端口 数据12端口就用12个线程去接收 。但处理都是一样的吧 。
所以要有个事件比如定义一个事件
public delegate void DataArrivalHandler(byte[] data);参数你定,或者(Streams)之类,也可以是自定一个类(包含其它信息)继承EventArgs写个 (DataEventArgs e)
public event DataArrivalHandler OnDataArrived;
OnDataArrived =()这里注册相应的方法,如果不同端口的处理不一样,就相应写不同的事件 , 当然也可以只定义一个方法,方法根据不同的端口处理 。
while(true)
{
byte[] data = https://www.04ip.com/post/(获取)
这里获取数据后,直接调用
OnDataArrived(data)/OnDataArrived(stream)/OnDataArrived(new DataEventArgs (data,ip,port)之类,根据你定义的参数来 。
}
而注册的方法里的具体实现,用委托异步调用.方法体里执行
{
namedDelegate.beginEnvoke();
}
这样,数据处理就异步完成了 。
避免数据丢失的话 , 做个保险 。把接收的数据放入定义的缓冲块里 。当接收的数据量到达一定程序后,取出部分处理,再加入新数据 。
类似于TCP的的滑动窗口 。麻烦点,但实现了,效果会好的多 。
--------------------------
为什么要用ThreadPool?不便于控制状态 。当你的线程处理的业务非常单一时用它,这种情况需要不需额外的状态信息,比如就像你上面的每次有不同的byte[] data 。
直接 new ThreadStart();
udp服务器怎么确定已经收到数据了呢,大佬帮忙解答下?服务器有没有收到数据 , 抓个包看看就行了 。
recvfrom和sendto都是阻塞的 。通常来说,由于网络连接具有缓冲区,sendto函数直接将数据复制至缓冲区后即可认为操作完成,因此很少阻塞(除非缓冲区已满,它才会等待缓冲区足够写入后才能操作);而recvfrom是从缓冲区读数据 , 如果没有数据则会一直阻塞 。
解决阻塞的方法一般有两种:使用setsockopt函数设置超时时长;在主线程中关闭socket,阻塞函数会报错并退出 。
php socket udp 通信与设备发送数据的程序编写人协调,在发送的数据前面添加一个标识设备ID的内容,这样接收数据后从数据判断设备号,而不是通过IP和PORT 。
例如约定用两位数表示设备ID,那么设备01发送的数据是AAAAA修改为发送01AAAAA,收到数据后识别01为设备号,后面的AAAAA作为数据 。
PHP服务端监听UDP通信方式例子代码:
?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$msg = "Ping !";
$len = strlen($msg);
socket_sendto($sock, $msg, $len, 0, '127.0.0.1', 1223);
socket_close($sock);
?
查看手册中相关的函数就知道进一步应该怎么编程 。
【phpudp接受数据 php 接收参数】关于phpudp接受数据和php 接收参数的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 多屏显卡锁屏宝怎么用,多屏显示显卡
- html5仿华为应用商城页面,html仿app
- gis晕线怎么弄,gis晕线怎么画
- linux时间矫正命令 linux时间校对
- 怎么把软件写进u盘,怎么把软件写进u盘里
- 安卓手机芯片怎样加密,安卓手机芯片怎样加密设置
- vb.net扫描ip cmd扫描ip
- 平凉农村电商如何发展,发展农村电商的可行性方案
- 怎么查看oracle数据库的版本号,查看oracle版本号sql