TServerSocket 用这个接收数据,发现有丢包,是丢最后一次的数据

west_2010 2018-01-06 06:49:39
各位大神,请教下,TServerSocket用这个的时候接收数据,最后一次的数据有时可以收到,有时收不到,不知道是数据的问题还是TServerSocket这里没处理好

void __fastcall TForm1::srvrsckt1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
//void *Buffer;
char *c_data = new char[Socket->ReceiveLength() + 1];
AnsiString s_temp;
TMemoryStream *stream = new TMemoryStream();
stream->SetSize(Socket->ReceiveLength());
stream->Position = 0;
Socket->ReceiveBuf(stream->Memory, Socket->ReceiveLength());
stream->Read(c_data, stream->Size);
//stream->SaveToFile("1.txt");
mmo1->Lines->Add(AnsiString(c_data));
delete stream;
delete c_data;
}
...全文
1787 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhgwbzhd 2019-02-16
  • 打赏
  • 举报
回复
没试过INDY么?那个控件比较简单好用。
huang714 2019-02-14
  • 打赏
  • 举报
回复
void __fastcall TForm1::srvrsckt1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
//void *Buffer;
char *c_data = new char[Socket->ReceiveLength() + 1];
AnsiString s_temp;
TMemoryStream *stream = new TMemoryStream();
stream->SetSize(Socket->ReceiveLength());
stream->Position = 0;
Socket->ReceiveBuf(stream->Memory, Socket->ReceiveLength());
stream->Read(c_data, stream->Size);
//stream->SaveToFile("1.txt");
mmo1->Lines->Add(AnsiString(c_data));
delete stream;
delete c_data;
}
abc_ustone 2018-02-17
  • 打赏
  • 举报
回复
可以这样,采取一来一回的方式: 客户端发送"getfile filename"字符串;服务器端打开文件流,发送流的大小信息; 客户端收到流的大小,发送"ready"字符串;服务器端发送流; 客户端(循环)接收流。
ooolinux 2018-02-10
  • 打赏
  • 举报
回复
如果发送时先SendText一个长度字符串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream发送流;接收时中间也要Sleep,不过毫秒数要小于发送中间Sleep的毫秒数。 如果不Sleep,数据容易串起来,导致接收错误。 不过长度可以用SendBuf发送一个int,就不用Sleep了,接收时代码稍微复杂一点。
west_2010 2018-01-24
  • 打赏
  • 举报
回复
@ooolinux 首先先谢谢你的回答,我会试下在srvrsckt1ClientRead事件里循环读取的,发送这里我控制不了,因为是设备自动发送,不知道设备是怎么样的发送机制,这里我只能控制我这边接收的,再次感谢。
ooolinux 2018-01-24
  • 打赏
  • 举报
回复
发送较大的流的话,用ReceiveBuf只接收一次肯定是不完整的,因为每次ReceiveBuf能收到的量都有限。
ooolinux 2018-01-24
  • 打赏
  • 举报
回复
发送、接收流之前,先发送、接收流的长度,也是比较常用的做法了。
ooolinux 2018-01-08
  • 打赏
  • 举报
回复
发送方可以先SendText一个长度字符串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream发送流。 ———— 这样不好,两次发送之间需要Sleep。 先SendBuf发送一个长度int就可以了,buf强制地址转换为int* 。
ooolinux 2018-01-07
  • 打赏
  • 举报
回复
发送方可以先SendText一个长度字符串,比如IntToStr(fs->Size),Sleep若干毫秒,然后SendStream发送流。 接收方OnRead的时候, if(!bHasSize) 就读取长度字符串,bHasSize=true。 else 循环ReceiveBuf读取流(当剩余长度>0),比如每次读取32K,每次ReceiveBuf的返回值是实际读取的字节数,或者没读到为-1。 还有一点要特别注意,OnRead事件处理函数是会重入的,在一个OnRead函数调用中循环读取流的时候,OnRead函数又会被调用执行,只要设置一个变量,碰到这种情况直接return就可以了。 还可以设置一个Timer,超时用变量标志从循环读取中退出。 可以用一个Memo来调试输出: Size: 119182 reading... remain: 119182 get: 4096 remain: 115086 return get: 24576 remain: 90510 get: -1 return remain: 90510 get: 24576 remain: 65934 get: 12288 remain: 53646 return get: 24576 remain: 29070 return get: 24576 return remain: 4494 get: 4494 Done! BCB 6.0本机调试每次ReceiveBuf最多24K,CB2010是8K。两机局域网调试每次ReceiveBuf一般不超过8K。
abc_ustone 2018-01-07
  • 打赏
  • 举报
回复
来看看
ooolinux 2018-01-06
  • 打赏
  • 举报
回复
循环ReceiveBuf的时候也许可以适当延时若干毫秒,还可以设置超时break退出循环。
ooolinux 2018-01-06
  • 打赏
  • 举报
回复
你可以试一下,我也刚接触TServerSocket 。
ooolinux 2018-01-06
  • 打赏
  • 举报
回复
一般ReceiveBuf到数组,数组写到MemoryStream吧,全部写完以后注意MemoryStream的Position 。 可以先SendText一个长度字符串,比如"L8192",收到L开头代表后面是发送流的长度,然后SendStream发送流, 读的时候if(!bHasLength)就读取长度字符串,bHasLength=true。else循环ReceiveBuf读取流(当剩余长度>0),比如每次读取1K,流太长了一次读取可能会有问题。

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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