关于socket服务器数据包分多次发送,客户端接收的问题

Coder_delphi 2012-04-05 02:51:50
1.服务器端一直在发送数据,由于发送的数据()较长,采用分段发送(send(Fsk, ServerSendArr, ActLen, 0)SendArr为自己定义的一个32字节的数组)的方法。
2.客户端接收数据(recv(Fsk,ClientRecvArr, RecvLen, 0)),接收到的ClientRecvArr存入TMemeryStream的对象FMemeryStream中
问题:
1. FMemeryStream 不可能一直增长下去,如果FMemeryStream的空间满了怎么办?
2. 如果FMemeryStream满了以后,直接从position 为0开始覆盖,则从此开始的包不是一个完整的怎么办?
本人初次接触,请大神们给点建议。
...全文
717 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
ok,貌似我应该是弄明白了,对MemoryStream 如果到了设定的大小,就从position = 0 开始对里面的数据进行覆盖,数据处理只针对于FCilentThread.FTempArr这个数组就可以了
处理代码:
FCilentThread.FMemeryStream.Position := 0;
FCilentThread.FMemeryStream.Read(FCilentThread.FTempArr, FCilentThread.FMemeryStream.Size);
if FCilentThread.FTempArr[FReadPosition] = $8F then
begin
OpenBiggerPack;
FReadPosition := FReadPosition + FCilentThread.FTempArr[FReadPosition + 2];
if FReadPosition > 65535 then
begin
j := FReadPosition - FCilentThread.FTempArr[FReadPosition + 2](包的第三位是包长);
for i := 0 to FCilentThread.FTempArr[FReadPosition + 2] - 1 do
begin
FCilentThread.FLastArr[i] := FCilentThread.FTempArr[j];
j := j + 1;
if j > 655535 then
begin
j := 0;
end;
end; //把最后一个包取出单独的放到一个数组内,但是并没有对该数组解包,相当于把这个包扔掉
FReadPosition := j;
end;
end;
end;
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
setSize设置它自己占的内存块的大小
山东蓝鸟贵薪 2012-04-06
  • 打赏
  • 举报
回复
MemeryStream
好像没有设置读取块的大小呀
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
额,我现在在想的问题是给memorystream 分配大小后,怎么解决越界问题,把Position设为0,重新覆盖?
mhhaifeng 2012-04-06
  • 打赏
  • 举报
回复
没什么好办法 指定 MemeryStream的大小 每次接收越界就存在下一个 MemeryStream中
MemeryStream 用Tlist 链接保存 可动态增减

每个MemeryStream分配的内在大小一定 分包 是必需做的了
山东蓝鸟贵薪 2012-04-06
  • 打赏
  • 举报
回复
1-6
1是第一组数据
6表示长度
山东蓝鸟贵薪 2012-04-06
  • 打赏
  • 举报
回复
这样也不行的,有时IP丢包也不能确定数据库的完整性呀
建议将数据分成几个块如下:
块序号 1-6 2-6
块信息111111 222222
将这两个块传递给服务器,去效验长度即可

kaikai_kk 2012-04-06
  • 打赏
  • 举报
回复
可以做成应答模式,即先定义好每次传輸的包大小,程序先传送数据长度
然後客户机每次接收完成并回复,服务嚣得到回复后再发送下一包(或其它操作)
直接接收到的总长度等于开始传过来的长度即表示结束
山东蓝鸟贵薪 2012-04-06
  • 打赏
  • 举报
回复
尽量将数据块少一些,这样会稳定些
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
while FNumPosition - FReadPosition < 126 do
begin
RecvCount1 := recv(Fsk, FCilentThread.FRecvInfo.ClientRecvData, RecvLen, 0);
if RecvCount1 > 0 then
begin
LastSize := FCilentThread.FMemeryStream.Position;
if LastSize + RecvCount1 <= 65535 then
begin
FCilentThread.FMemeryStream.Write(FCilentThread.FRecvInfo.ClientRecvData, RecvCount1);
FNumPosition := FNumPosition + RecvCount1;
FCilentThread.FMemeryStream.Position := FNumPosition;
end
else
begin
FCilentThread.FMemeryStream.Write(FCilentThread.FRecvInfo.ClientRecvData, 65535 - LastSize);
FCilentThread.FMemeryStream.Position := 0;
FReadPosition := 0;
FCilentThread.FMemeryStream.Write(FCilentThread.FRecvInfo.ClientRecvData[LastSize + RecvCount1 - 65535], LastSize + RecvCount1 - 65535);
end;
// if FNumPosition - FReadPosition > FCilentThread.FRecvInfo.ClientRecvData[FReadPosition + 2] then
// Break;
end;
end;
FCilentThread.FMemeryStream.Position := 0;
FCilentThread.FMemeryStream.Read(FCilentThread.FTempArr, FCilentThread.FMemeryStream.Size);
if FCilentThread.FTempArr[FReadPosition] = $8F then
begin
OpenBiggerPack;
FReadPosition := FReadPosition + FCilentThread.FTempArr[FReadPosition + 2];
end;
这是我的代码,写的很麻烦,思路是把FCilentThread.FRecvInfo.ClientRecvData接收的数据不断的给memorystream,然后从memorystream中取出数据给FTempArr,对FTempArr进行解包操作
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
可以接收并显示数据的,但是越界以后数据就不改变了
山东蓝鸟贵薪 2012-04-06
  • 打赏
  • 举报
回复
你先在本机上测试一下试试看看能不能接受呀,
Coder_delphi 2012-04-06
  • 打赏
  • 举报
回复
可能超过1g,因为服务器是不断的在发送数据的,单次发送的话没有1g,我就是把服务器发来的数据不断存到memorystream里面去,事先给它setsize一下,就是不知道怎么解决它的越界问题。
BambooCaep 2012-04-05
  • 打赏
  • 举报
回复
memorystream会动态从堆空间里获取内存。如果获取内存都失败了,那就该换用filestream了。话说服务器发送的数据超过1g了么?

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧