|
|
导航: |
论坛 -> 网络通讯
斑竹:liumazi,sephil |
|
作者: |
|
2019/4/3 7:47:19 |
标题: |
|
加入我的收藏 |
楼主: |
需要接收和发送大量数据,(600K),但是IdTCPServer每次只能接收一部分,本来想拼接起来,但是过程太容易出错了,怎么能全部接收呢。有没有相应的例子,谢谢!
----------------------------------------------
- |
作者: |
|
2019/4/3 8:03:23 |
1楼: |
嘻哈 序列 长度 数据 MTU 1500字节 发1024字节 比较好。
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
|
作者: |
joman (joman) |
▲▲▲▲▲ |
-
|
普通会员 |
|
2019/4/3 8:06:28 |
2楼: |
组包 头尾长度包体
----------------------------------------------
DelphiWeb开发方案(开源):https://gitee.com/pearroom/DelphiWebMVC
|
作者: |
|
2019/4/3 8:44:43 |
3楼: |
keymark:发的字节没法控制,是硬件已经决定了,一次发过来那么多,上位机只能被动接收。 joman :地下发过来的有帧头帧尾,但是数据量有点大,一次接收不了,容易出问题,导致没法组成帧。有没有相应的实例,谢谢!
----------------------------------------------
-
|
作者: |
|
2019/4/3 9:20:39 |
4楼: |
tcp的粘包问题,到处是实例。既然有帧头和帧尾了已经是很标准的模式了: 1.tcp收到数据后放入接收缓冲区 2.从接收缓冲开始,取帧头长度的数据,和帧头比较一下是否相同,如果相同标记新数据开始,如果大小不足600K,则将接收缓冲区的数据移入数据缓冲区; 3.继续接收,判断收到的长度和数据缓冲区的现有长度相加是否到了600K,没到就把接收到的放到数据缓冲区尾;如果相加>=600K,则数据缓冲区凑整600K后触发收到完整帧的事件,如果相加>600K,要将和原数据缓冲区补齐600K后剩余的数据重新做为数据开始; 4.重新第1步;
----------------------------------------------
18114532@qq.com
|
作者: |
joman (joman) |
▲▲▲▲▲ |
-
|
普通会员 |
|
2019/4/3 11:21:17 |
5楼: |
要自己组装,比如你的 有效长度是10 你可能接了15个字节 你只取10个剩下5个存储再接后面的累加,可能是20了,还是只取10个 只要符合长度和头尾的,剩余的下次再累加 ,两个线程 一个取一个算
----------------------------------------------
DelphiWeb开发方案(开源):https://gitee.com/pearroom/DelphiWebMVC
|
作者: |
|
2019/4/3 11:25:13 |
6楼: |
首先,tcp协议粘包和分包是很正常的。 第二,你用indy做服务端么?这个就祝你好运了。
----------------------------------------------
--
|
作者: |
|
2019/4/3 15:15:53 |
7楼: |
bahamut8348
难度INDY是个坑? 那你们一般用什么做服务器,谢谢!
----------------------------------------------
-
|
作者: |
|
2019/4/3 18:20:55 |
8楼: |
一般做服务端程序,我首先就会把delphi排除在外。 这种一言不合就抛异常的东西,还真是不好惹。 还有就是,在这方面,delphi可用的三方资源太少。
给你个方案: 一:最快速的方案就是使用nginx或者apache这种开放式的成熟高可用性的服务端去处理数据收发,你只需要关注业务部分就可以了。 二:使用开放的三方库,个人建议是libev或者libevent,开源跨平台。 三:如果你一定要吊死在delphi上,建议你去看看mORMot这个三方库。 四:如果你一定要自己折腾的话,直接用select模型做tcp是做不起来的。建议你去看看网络模型;windows系统去研究研究iocp模型,linux去研究研究epoll,freebsd上去研究研究kqueue。
----------------------------------------------
--
|
作者: |
|
2019/4/3 18:50:42 |
9楼: |
我客户端、服务端一直用 Delphi,7*24运行良好。 Delphi有源代码,不知道修改吗? indy 抛的异常,可以将抛异常的源代码复制到本目录下,进行修改(2个文件)。
第三方控件的BUG,比 Delphi 自带的代码BUG,多多了。
----------------------------------------------
武汉天气不好
|
作者: |
|
2019/4/4 7:41:36 |
10楼: |
想省事,用8楼,想费劲,用9楼。水平不行的话,8楼9楼都没用。
----------------------------------------------
Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!Delphi威武!千秋万代,一统江湖!我去WC吐一会儿去!
|
作者: |
|
2019/4/4 9:09:26 |
11楼: |
抛异常是好事啊。说明开发人员认真。 我们懒人写的,就不抛异常,瞎执行。不能执行,也强行执行。
而且 我 8 楼 9 楼的 都没用上。 说明我不仅仅懒,水平还低。
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
|
2019/4/4 10:24:48 |
12楼: |
我只是传个数据,没那么复杂,可能我水平不行,目前遇到的问题确实比较多,IdTCPServer动不动就假死
----------------------------------------------
-
|
作者: |
|
2019/4/4 11:09:44 |
13楼: |
不抛异常不表示就不管错误。去参照一下win32的api是怎么报错的。 至于能运行良好,如果没执行几次逻辑,只要没有明显错误的程序都可以运行良好。 也别扯什么改人家代码,我有那个时间不如找个更稳定、扩展性更强的。而且还跨平台。
至于楼主的问题,8楼已经说了,不在重复了。
----------------------------------------------
--
|
作者: |
|
2019/4/4 11:16:48 |
14楼: |
idtcpserver根本不存在粘包问题
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
|
作者: |
|
2019/4/4 18:36:54 |
15楼: |
14楼,是存在的,比如发送那边发个10K的数据过来,这边接收的时候可能是1+1+8,也可能是2+3+5等各种组合,但是不会一次收10K
----------------------------------------------
-
|
作者: |
|
2019/4/15 3:18:37 |
16楼: |
沾包这个说法,明显是不懂 TCP 的人发明的。TCP 就是根水管,里面都是流。这个流如何断句,那是你自己的问题,不是 TCP 的问题。
抛异常是非常好的代码模式。如果程序有异常但你要继续执行,你把异常处理好就行了。不是说有异常程序就会中断或者就会崩溃。用 TIdTCP 那一套控件的话,你把异常处理好了,连续运行不会有事的。俺对 TIdTCPServer 做过压力测试。
15楼,一次收多少个数据不是问题。问题是你要知道你应该收多少数据。假设你知道你应该收 4096 个Byte,那么,你创建一个流(TStream),收到几个就丢进去几个,收够为止。不就完了?二进制字节流的处理,概念其实很简单。
----------------------------------------------
-
|
作者: |
|
2019/4/15 9:36:04 |
17楼: |
听大佬说过 包可能会错序 。。有这回事吗?
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
|
作者: |
gmxyb (gmxyb) |
★☆☆☆☆ |
-
|
普通会员 |
|
2019/4/15 9:49:39 |
18楼: |
赞同16楼,划重点:
【沾包这个说法,明显是不懂 TCP 的人发明的。TCP 就是根水管,里面都是流。这个流如何断句,那是你自己的问题,不是 TCP 的问题。】
至于17楼说的“包可能会错序”,这也是不懂 TCP 的“大佬”在胡说八道、信口开河。。
----------------------------------------------
-
|
作者: |
|
2019/4/15 10:44:10 |
19楼: |
顶 16 18 楼。
TCP 的问题在于,另一头说 打算发 100个字节给我。 我说,我知道了,你发吧。 结果,对方发了 99 个不发了。 我怎么办?我只能等啊。所以,有一个 超时。 多长时间,对方不发数据,就会超时。 超时,我也只能等啊。 万一我放弃了,对方突然发过来呢。
不过,喜欢的话,可以通知对方,老子不等了,断开连接,剩余的数据 老子不要了。 你爱发不发。 我重新发起一次请求。 这次 你还超时。 我提示 ,对方 无响应!
http 就是 简单的 tcp 。 post get put head 四个命令而已。 ftp 命令就多一些。 都是 TCP 应用。 http 喜欢不保持连接。 比如发一个 GET 命令,接收完数据,就断开了。 服务器 想 主动 发点数据,都不知道该怎么发。
FTP 不一样,需要 一直连着。
不过 FTP 一样是 客户端 提交 请求的,服务器 才会 回复。人家 从来就没打算 服务器 主动发消息给 FTP 客户端。
http 表现出 一直联网的方法就是 ajax。简单的说,就是 轮询。
轮询,到了手机上,就是 费电。非常费电。 所以 各个厂家,都希望 APP 不要轮询。
腾讯 只好 和 各个厂家 要 他们的 接口 API。 谷歌 苹果的 接口比较通用。 但是 很多厂家,也有自己的接口。 用 接口 API ,实现 推送。 是 腾讯的做法。 但是 腾讯 收集的接口多了,也就开发出自己的 推送 服务器了。 给那些 厂家 懒得做自己接口的手机用。
极光等第三方,也是一样的道理。 他们 也是 和 各个厂家 要 API 。然后 自己的 推送服务器 负责 那些 没有 API 的厂家。
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
|
2019/4/15 11:42:37 |
20楼: |
学习了!
----------------------------------------------
喜欢Delphi,关注Delphi,愿和广大爱好者交朋友。
|
作者: |
|
2019/4/15 12:28:56 |
21楼: |
粘包,也许是在客户端发送的时候就粘包发送了呢?,查清楚,在根上找原因
----------------------------------------------
-
|
作者: |
|
2019/4/16 11:30:24 |
22楼: |
接收设备的数据,以及网络不好,才会有这类问题。
说好发8K,PC真的就会一次发8K,不管网络上传输时被拆成什么样子(MTU), 收到的时候都是拼好的。 设备发的话,可能就会一会儿发4K,一会儿发5K(带着下一个包的数据)。
SERVER通常也不会设置很长的超时。
但,不管数据包多大,4楼的做法不是挺好的吗? 收数据,添加到缓存区末尾,取现在缓存区长度,大于包长度后取包出来处理; 缓存区移除处理的包的数据,剩余数据整体MOVE到开头,调整缓存区长度。 剩余数据长度大于包头长度,取下一个包的长度,看剩余数据长度是否大于缓存区长度,如大于,取包出来处理直到剩余长度不足等待接收数据
----------------------------------------------
-
|
作者: |
|
2019/4/16 12:02:38 |
23楼: |
第三方都做好的事情,非要自己写代码。都是牛人。
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
|
2019/4/18 13:04:04 |
24楼: |
indy 很好啊,谁在黑我们的伟大的 indy!
----------------------------------------------
kittyapp
|
作者: |
|
2019/4/18 14:33:07 |
25楼: |
24楼,有没有用indy做的收发数据的例子,学习一下,谢谢!
----------------------------------------------
-
|
作者: |
|
2019/4/22 1:55:47 |
26楼: |
25楼,Indy 官方的 Demo 很多,去网上搜。其他人写的例子代码网上也很多。我老人家也在网上发过用 Indy 写的例子代码。
21 楼,你说的【粘包,也许是在客户端发送的时候就粘包发送了呢?】,这个是不存在的。再重复一遍,TCP 没有粘包这个荒谬的概念。
在客户端,假设你要发送2个包,每个包100字节。你可以100字节发完,再发100字节,看起来是发了2个包。你也可以一个字节一个字节地发,发完200个字节为止。你也可以一会发10个字节,一会发20个字节。随便你,都没关系。你用 Delphi 发出去的字节,都会存入 Windows 底层的 TCP/IP 协议栈里面给你开的 buffer,然后呢,Windows 看网络速度如何,网络速度快它发得快,网络速度慢它发得慢。至于它发出去的数据是一个一个的字节还是一个一个的包,在 TCP 层来看,所谓的包是不存在的,没有意义的。就是一个一个字节的字节流。
----------------------------------------------
-
|
作者: |
|
2019/4/22 8:57:26 |
27楼: |
d7 时代的 网络程序用 INDY 很多啊。 那时候 一个 server 一个 client 两个 exe ,标准的 cs 人家运行得也很好啊。
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
|
2019/11/11 12:02:21 |
28楼: |
如果服务器端使用,还是建议使用iocp,性能要好的多。 不过发送和接收自定义数据的粘包,是需要自己解决的。
----------------------------------------------
-
|
作者: |
|
2019/11/11 12:14:13 |
29楼: |
看了 一下 回复,22 楼 4楼虽然说得正确,但是过程过于复杂。 还是 16楼做法简单高效。用不用随意。信不信也随意。
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
sspeak (sspeak) |
★☆☆☆☆ |
-
|
盒子活跃会员 |
|
2019/11/11 12:23:35 |
29楼: |
最好了解下TCP/IP的概念. IP只管每个包的寻径,到达. TCP,发送端,负责分包,发送,出错时反复发送,各个包的路径/到达顺序不定. TCP,接收端,负责组合包,纠错,通知发送端重新发送错误包. 从原理上来说,TCP保证数据的无错传输,除非网络发生不可抗错误. 在TCP/IP之上的应用协议不需要关心包,只需要知道何时开始何时结束.
----------------------------------------------
-
|
作者: |
sspeak (sspeak) |
★☆☆☆☆ |
-
|
盒子活跃会员 |
|
2019/11/11 12:31:12 |
30楼: |
16/18楼,错了,分包是TCP的事,包也会错序到达,但这些都会在TCP层被纠正.
----------------------------------------------
-
|
作者: |
sspeak (sspeak) |
★☆☆☆☆ |
-
|
盒子活跃会员 |
|
2019/11/11 12:38:02 |
31楼: |
TCP/IP协议的初衷,就包含在战争情况下保证可靠性,因此数据网络中有多个节点,每个包独立传输,因此各个包会按不同路径到达,到达顺序也不求相同.
----------------------------------------------
-
|
作者: |
|
2019/11/11 14:05:45 |
32楼: |
我感觉 楼上 和 16 18 楼 的意思一样。 都是 TCP 内部处理好了,使用 TCP 的人,不需要考虑这些。 这个理解对吗?
----------------------------------------------
(C)(P)Flying Wang
|
作者: |
hs_kill (lzl_17948876) |
★☆☆☆☆ |
-
|
普通会员 |
|
2019/11/11 16:16:24 |
33楼: |
难道回复的时候都不看下前面的回复时间么 一个4月份的帖子过了半年多被挖坟挖出来还回复的这么快乐.......
----------------------------------------------
http://www.cnblogs.com/lzl_17948876/
|
作者: |
|
2019/11/11 20:21:29 |
34楼: |
挖坟,鞭尸。明年再见
----------------------------------------------
!!!!!!!
|
作者: |
|
2019/11/12 10:29:06 |
35楼: |
30 楼,再强调,TCP 没有包的概念,是流,Stream。
你说 TCP 分包,包错序到达,这个是 TCP /IP 协议栈的事,不是使用 TCP 的人的事。
搞软件,千万要把你当前讨论的概念所在哪一层搞清楚。不要把 TCP 底下的事和 TCP 上面的事混为一谈。使用 TCP 的人,没有包的概念。至于 TCP 分包,那是分成了 IP 包,是 IP 通讯的概念,是 TCP/IP 协议栈处理的,和应用层代码完全无关。
再重复一遍,应用层代码看 TCP,就是一个字节流。比如你要发一个你的数据包,有1K字节,你可以写一个循环,循环一千次,一次发一个字节,也是没问题的,对于接收端来说,和你一次发送一千个字节,没有任何区别。
33楼,技术问题,时间不重要。如果重要,我记得第一个 TCP/IP 协议栈是上个世纪70年代写出来的,那现在还讨论个鬼?
----------------------------------------------
-
|
作者: |
|
2019/11/12 11:15:23 |
36楼: |
一个问题半年了还在回? “沾包这个说法,明显是不懂 TCP 的人发明的。” 呵呵、呵呵呵呵
----------------------------------------------
--
|
|