奇怪的丢包问题。

zengyh 2003-01-13 09:25:40
我服务器端用多线程TCP/IP通讯,但是我用SendBuf(buf,len)发送数据时,返回的也为len,但是我的len为100个字节,对方却只收到不到10个。

对方是采用串口转化为TCP/IP的方式,我自己在UNIX下写了个客户端,收发数据是没有问题的,问题会出在哪?

请各位老大帮忙!!!
...全文
77 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
痞子酷 2003-01-15
  • 打赏
  • 举报
回复
你用同步方式试试,你讲缓冲区设置大一点试试,
winSock-->unixSock :异步 包文件大,丢包
同步 包文件大,不丢包
unixSock-->winSock :异步 包文件大,不丢包
同步 不丢包
l_clove 2003-01-15
  • 打赏
  • 举报
回复
我不知道有没有更好的方法。
用活动连接数来控制活动的连接,应该可以
zengyh 2003-01-15
  • 打赏
  • 举报
回复
谢谢,我知道了,也解决了。
能限定接入的连接数吗?
zengyh 2003-01-15
  • 打赏
  • 举报
回复
我现在就是用同步的。谢谢ouygg(痞子酷)
zengyh 2003-01-14
  • 打赏
  • 举报
回复
我做了超时的判断,就是说连接建立起来后,如果在规定的时间内没收到数据,则断开此连接,但主服务进程不能断开,必须继续侦听。

我开始这样写:
{
timeCount++;
if((ServerSocket1->Active==false)||(ServerSocket1->Socket->Connected==false))
{
timeCount=0;
return;
}
if(timeCount>timeout*60)
{
WriteLog("%d分钟内没收到数据,断开连接",timeout);
ServerSocket1->Socket->Close();
}
return;
}

我以为判断是否侦听,用
if(ServerSocket1->Active==false)
判断是有新建立了连接,用
if(ServerSocket1->Socket->Connected==false)
但我发现,只要在侦听,后者就为真,其实二者都是判断是否侦听。

那么判断是否连接用什么?
关闭连接用什么?

请各位帮忙。
zengyh 2003-01-14
  • 打赏
  • 举报
回复
不过,我还是按你说的改了。
因为我socket控件放在主窗体,在Connect函数里处理,因为它一直停留在那个函数里,所以主窗体处于挂起的状态。因为我有个交易来回发交易好几分钟,所以还是在onread()函数中处理,因为该函数每处理一次都会退出。故主窗体是活动的。

如果你要做,通讯的另外建一个窗体就没问题了。

之所以丢包,是因为我在 SendBuf后用了Socket->Close()函数,对方速度慢,还在缓冲中没发完我就关闭了。而客户端我用局域网写的模拟从来不会丢。

还是谢谢你,给了我很好的提示。

对了,在多线程中的丢包问题我还是没有解决,sigh!主要是没时间,只能先应付着,以后再优化。
l_clove 2003-01-14
  • 打赏
  • 举报
回复
你的想法很好:)
我刚才用你的服务器代码试了一下,没丢包...
void __fastcall TForm1::ClientSocketConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
char buf[1000];
memset(buf, 'c', 1000);
Socket->SendBuf(buf, strlen(buf));
Socket->Close();
}
zengyh 2003-01-14
  • 打赏
  • 举报
回复
OnClientRead只是在数据到达的时候触发的呀。但是读取数据还是得自己实现。

如果按事件来处理,并不好。
如果交易只来回传送一次,在Read和在Connect里没有区别。
我在Connect里循环检测,有数据就读,处理完后就写回。完成了就退出了,按照我的理想化的方式,这个时候最好Close()掉,整个连接交易结束了,不要再做任何事情。

如果交易来回多次。那么我得声明个全局变量来处理,并且在判断交易是否终结,以及可能多个人发送过来的交易里,会数据难分开。
l_clove 2003-01-14
  • 打赏
  • 举报
回复
你不用使用循环来接收所有的数据,在有数据到达时,Socket会自动触发OnRead事件,你只要在其中编代码就可以了
l_clove 2003-01-14
  • 打赏
  • 举报
回复
那就是说,在Close以前,while一直循环了?
可是你想,OnConnect事件只执行一次的,而且是在连接刚刚建立的时候,当你Close后,下面的ReceiveBuf并未执行,只有你说的那种情况了,建议你这样改一下试试:
Client在OnConnect发送数据(保证实时),
Server的接收代码放在OnClientRead事件里,
zengyh 2003-01-14
  • 打赏
  • 举报
回复
to l_clove(苦丁香)
不是死循环,因为Socket->Close();
所以while()循环条件不成立,会退出该函数。

就是这个函数造成对方丢包。所以我在后面的贴子中直接用return关闭掉。

其实,很希望用多线程并发,但是即使我不用Close(),还是会丢包。

这个问题我没解决。
希望大家指点。
l_clove 2003-01-14
  • 打赏
  • 举报
回复
一睡不醒,好主意
三杯倒 2003-01-14
  • 打赏
  • 举报
回复
加上
sleep(0)
l_clove 2003-01-14
  • 打赏
  • 举报
回复
hi,你的客户端代码呢,在Client端的OnConnect中发送数据了么?
无论发不发, while(Socket->Connected==true)
{
memset(buf,0,sizeof(buf));
if((receivelen=Socket->ReceiveBuf(buf,1024))>0)
{
display_buf("new.log",buf,receivelen);
memset(buf,0,sizeof(buf));

for(int i=0;i<102;i++) {
buf[i]=0x01+i;
}
Socket->SendBuf(buf,102);
Socket->Close();
display_buf("new.log",buf,102);
}
}
这都是一个死循环啊,服务器那有机会去处理其余的包了
l_clove 2003-01-14
  • 打赏
  • 举报
回复
我又来了:)
ServerSocket有一个属性,Socket->ActiveConncetions记录了当前活动的连接数,Socket->Connections[i]表示第i个活动的连接,我想应该能解决你的问题了
zengyh 2003-01-13
  • 打赏
  • 举报
回复
对了SendBuf返回的字节数是不是写入发送缓冲区的字节数,并不是对方已经成功收到的字节数,对吗?

如果对方收得过快,会导致数据未读完,但我这边些入缓冲的还是整个数据,对吗?

刚才我用while循环发送,中间Sleep(2),但对方居然只收到一个字节。

没办法,看来不是发送过快的问题了。
zengyh 2003-01-13
  • 打赏
  • 举报
回复
我重新写了个最简单的。
程序如下:
void display_buf(char *file,char *buf,int len)
{
FILE *fp;
fp=fopen(file,"a");
for(int i=0;i<len;i++)
{
fprintf(fp,"%02x ",buf[i]);
if((i+1)%16==0)
fprintf(fp,"\n\n");
}
return;
}
void __fastcall TForm1::ServerSocket1ClientConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
char buf[1025];
int receivelen=0;
while(Socket->Connected==true)
{
memset(buf,0,sizeof(buf));
if((receivelen=Socket->ReceiveBuf(buf,1024))>0)
{
display_buf("new.log",buf,receivelen);
memset(buf,0,sizeof(buf));

for(int i=0;i<102;i++) {
buf[i]=0x01+i;
}
Socket->SendBuf(buf,102);
Socket->Close();
display_buf("new.log",buf,102);
}
}
}
//-----------

居然还丢包!my god,真要疯了。是不是BCB的控件本身就不是很好。
zengyh 2003-01-13
  • 打赏
  • 举报
回复
我没有用别的线程。就一个连接,我自己写的客户端是没有问题的。

netsys2 2003-01-13
  • 打赏
  • 举报
回复
易可不可以全在ClientConnect()函数中处理,也就是说读、数据处理、回写都在该函数中处理。或者都在ClientRead()处理?

------->可以
l_clove 2003-01-13
  • 打赏
  • 举报
回复
被别的线程劫走了?:)
加载更多回复(5)

1,317

社区成员

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

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