为啥我的workerman作为TCP客户端连接PLC,设置tcp_nodelay不生效,要解决怎么?

zgh419566

TCP客户端代码如下:
截图

程序启动后,逐个向服务器设备发送数据
截图

问题:代码中明明分开发的数据,在抓包时发现内容会自动连接在一起后才发出去。
收数据也一样,明明分开拿 数据,会被合成一起才送给应用程序。
截图

查了PHP环境支持的
<?php
echo function_exists('socket_import_stream');

php test_socket_import_stream.php
1

是否需要修改哪里的配置才能解决这个问题?

[www@linux beckhoff_ads]$ php start_ads_client_wkm.php start
Workerman[start_ads_client_wkm.php] start in DEBUG mode
------------------------------------------- WORKERMAN --------------------------------------------
Workerman version:4.0.41          PHP version:7.4.28           Event-Loop:\Workerman\Events\Event
-------------------------------------------- WORKERS ---------------------------------------------
proto   user            worker          listen          processes    status           
tcp     www             none            none            1             [OK]            
--------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
2022-08-01 06:15:28 Send 000020000000c0a8013401012103c0a801640101228004000400000000000000000000000000
2022-08-01 06:15:28 Send 00002c000000c0a801340101c800c0a8016401012180020004000c0000000000000001000000010000002100000010000000
2022-08-01 06:15:28 Send 000020000000c0a8013401012003c0a801640101218001000400000000000000000002000000
2022-08-01 06:15:28 Send 00002c000000c0a8013401012003c0a8016401012180010005000c0000000000000003000000010000002100000010000000
2022-08-01 06:15:28 Send 000021000000c0a8013401012103c0a80164010122800150000001000000000000000400000001
2022-08-01 06:15:28 Send 000021000000c0a8013401012103c0a80164010122800150000001000000000000000500000011
2022-08-01 06:15:28 Send 000022000000c0a8013401012103c0a8016401012280015000000200000000000000060000005112
2022-08-01 06:15:28 Send 000022000000c0a8013401012103c0a8016401012280015000000200000000000000070000005110
2022-08-01 06:15:28 Send 000022000000c0a8013401012103c0a8016401012280015000000200000000000000080000003800
2022-08-01 06:15:28 Send 0000a0000000c0a8013401012103c0a8016401012280015000008000000000000000090000005014050000000400480000000100000004004d00000006000000f9ff2200080000000100000000000400160000002800000004005100000002000000f9ff2200080000000100000000000400160000002800000004005100000002000000f9ff2200080000000100000000000400160000002800000004005100000002000000
2022-08-01 06:15:28 Connect Ok
2022-08-01 06:15:28 recv 000028000000c0a8016401012280c0a8013401012103040005000800000000000000000000000000000005000000000038000000c0a8016401012180c0a801340101c80002000500180000000000000001000000000000001000000050000000102700000100000000000000000038000000c0a8016401012180c0a80134010120030100050018000000000000000200000000000000020b3a08504c4320536572766572000000000000

2022-08-01 06:15:28 recv 0000ee000000c0a8016401012280c0a801340101210301500100ce0000000000000004000000e803e8030000000000003080000000ff00000000010000ff0000881300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000c0a8016401012280c0a8013401012103015001000600000000000000050000000000c0990400000024000000c0a8016401012280c0a80134010121030150010004000000000000000600000000001200000061000000c0a8016401012280c0a80134010121030150010041000000000000000700000000001000000000000000000000000000000000cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd000000000000000000000000000000000000cdcdcdcd00000022000000c0a8016401012280c0a8013401012103015001000200000000000000080000000000

2022-08-01 06:15:28 recv 000024000000c0a8016401012280c0a80134010121030150010004000000000000000900000000001400
171 2 0
2个回答

walkor

tcp协议是基于流的,不会自动将请求分开。收到的数据可能是一个请求的部分数据,也可能是多请求数据连在一起。
使用tcp时需要用应用层协议从数据流里区分请求边界,这就是为什么有了tcp,还要有http ftp smtp这些应用层协议。
tcp_nodelay 也不是用于分割请求的

  • zgh419566 10天前

    根据网上的参考资料,开启tcp_nodelay以后,执行send指令数据会马上送出去,收到数据,程序会马上产生onmessage事件。 ( https://www.cnblogs.com/zhangkele/p/9494280.html) 目前我们使用workerman做工业控制 ,连接倍福(beckhoff)PLC ,我再研究一下。感谢walkor.

  • zgh419566 10天前

    beckhoff官方的C++驱动程序默认开启了tcp_nodelay,可以做到数据即时收发的。 https://github.com/Beckhoff/ADS/blob/master/AdsLib/Sockets.cpp (line 229 setsockopt )。 而swoole也有这个特性 , workerman比swoole简单,所以才选择的这套方案。
    我看了workerman的源码,也有这个特性,worker.php line 2296,但是看样子设置没有生效,麻烦walkor再帮解答一下。

  • zgh419566 10天前

    再此表达一下,workerman的tcp reconnect功能 很好使,网络连接断开以后会自动重连,而swoole不一样,连不上就直接报错了,connected状态也依然为true,所以才选择的workerman。

  • walkor 10天前

    tcp_nodelay应该是生效了的,只不过 tcp_nodelay 无法从根本上解决你的问题,tcp的特性就是这样,数据没有边界,需要接收端从数据流里将完整的数据提取出来。

    快速发送数据或者网络延迟或者对端接收数据不够快都会导致数据在socket缓冲区积压,数据就连在一起了。

ysxpark

里面不是有个text协议吗,用/n分包挺好用啊

  • zgh419566 5天前

    感谢支持,但是对端TCP服务器是PLC硬件,协议里面定义的方式就是这样。

🔝