环境: win2000, VC6.0,server与client在同一台机器上运行
过程: 1、创建基于CSocket的socket server、socket client
2、两边都用CArchive进行数据发送、接受(client发送、server接受)
3、socket client以5毫秒为间隔(在OnTimer发送数据),向server发送大数据包
(测试时试过1K、2K、4K、10K、30K不同大小的数据包)
4、socket server接受到数据后不进行任何其它操作,直接丢弃
5、server用while循环持续接受数据,用CArchieve.IsBufferEmpty()
判断是否退出循环。
结果:1、当发送1K的数据包时,没有出现问题
2、发送2K的数据包时,客户端偶尔会出现死机
3、发送4K的数据包时,客户端大概发送100多个数据包就死机了,偶尔可以
连续发送几千个不出问题。
4、当发送10K、30K时,客户端发送的包不会超过100个,最糟糕时发送10来多
就死机了。
5、当客户端死机时,服务端还可以正常工作
另:在IsBufferEmtpy前面加上Sleep(5)语句后,如果只有一个客户端
发送数据,则客户端运行正常,不会出现死机现象。但如果客户端有多个,
则后面运行的客户端运行一会儿后就死机了!!!
不知有没有谁也碰到这些问题?????那位兄弟给偶解答解答
51 个解决方案
#1
我觉得你的问题都是因为CArchive和CSocket的联合使用的问题,我作过类似的测试,不过是用的SOCKET2。0 API函数,发送100MB的数据包都没有问题,1000MB的时候就出错了~~~
我不太喜欢那样用SOCKET,个人建议~~~
我不太喜欢那样用SOCKET,个人建议~~~
#2
是啊,为什么要使用CSocket呢?呵呵。
to wlrwx,1000MB的数据包? 一个包1000MB?不会吧。
to wlrwx,1000MB的数据包? 一个包1000MB?不会吧。
#3
socket client以5毫秒为间隔?
你能保证5毫秒内数据都能发出去吗???
你能保证5毫秒内数据都能发出去吗???
#4
lanfan说的有理,有可能会有包还没发出就被新来的包冲掉了,接受时也一样。
#5
to wlrwx():
CArchive与CSocket联合使用的问题能不能详细说说??
to neccui(PPC):
我也不喜欢用CSocket,只是有一段现成的代码是用CSocket的。为了赶时间,如果可以满足性能想将就一下。
to lanfan:
没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机。
CArchive与CSocket联合使用的问题能不能详细说说??
to neccui(PPC):
我也不喜欢用CSocket,只是有一段现成的代码是用CSocket的。为了赶时间,如果可以满足性能想将就一下。
to lanfan:
没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机。
#6
我推!!!!!!!!!!!!
#7
才9点,怎么就没人了???难道程序员也泡妞???????????
#8
关注,vtable9999,我和你用的方法一样,CSocket和CArchive联合传送数据,
但是我传数据间隔的时间不定,通常十秒3个数据包,每个包50k左右,多的时候,连续不断的传200多个数据包,每个包50k.
我的程序也是会出现客户端程序死机的情况,请教!
但是我传数据间隔的时间不定,通常十秒3个数据包,每个包50k左右,多的时候,连续不断的传200多个数据包,每个包50k.
我的程序也是会出现客户端程序死机的情况,请教!
#9
to waterdrop31(水滴): 帮我推推,一定要把问题解决了
#10
TCP协议本身的缓冲是有限的,默认是48K. 所以发送数据最好在一个:
while(1)
{
send();
......
这样,即使缓冲满了,send()也会自动挂起。
while(1)
{
send();
......
这样,即使缓冲满了,send()也会自动挂起。
#11
试一试这段Code, 我想应当确定数据报已经被送出:
for(DWORD t = GetTickCount() +300; (bytes < sizeof(msg) && GetTickCount() < t);)
{
bytesent = send(msocket, (const char*)&msg+bytes, sizeof(msg)-bytes, 0);
if(SOCKET_ERROR == rc)
{
err = WSAGetLastError();
if(err != WSAEWOULDBLOCK)
{
return -1; // TODO: log error
}
else
Sleep(1); // take a break
}
else
{
bytes += bytesent;
}
}
for(DWORD t = GetTickCount() +300; (bytes < sizeof(msg) && GetTickCount() < t);)
{
bytesent = send(msocket, (const char*)&msg+bytes, sizeof(msg)-bytes, 0);
if(SOCKET_ERROR == rc)
{
err = WSAGetLastError();
if(err != WSAEWOULDBLOCK)
{
return -1; // TODO: log error
}
else
Sleep(1); // take a break
}
else
{
bytes += bytesent;
}
}
#12
ok, 马上汇报测试结果
#13
糟,没法测试
#14
yes, for the OS, there is a sending buffer and a receiving buffer,
and the buffer size is fixed, if you send too much data frequently,
you may fail to send the data, for the receiving part, it is the same. so in communication program, you'd write some functions such as: sendDataWait(...), sendDataTimeout(...), recvDataWait(...), recvDataTimeout(...).
eg: for sendDataWait(...), if the sending buffer is full, then you call select() function to test if it is ok to send data, you may find that no data can be sent, at this time, you have to wait.
for the timeout function, it is only to not to block. if i can't send the data in a certain time, maybe the network is not reliable.
and the buffer size is fixed, if you send too much data frequently,
you may fail to send the data, for the receiving part, it is the same. so in communication program, you'd write some functions such as: sendDataWait(...), sendDataTimeout(...), recvDataWait(...), recvDataTimeout(...).
eg: for sendDataWait(...), if the sending buffer is full, then you call select() function to test if it is ok to send data, you may find that no data can be sent, at this time, you have to wait.
for the timeout function, it is only to not to block. if i can't send the data in a certain time, maybe the network is not reliable.
#15
to Lchaos(nicky):
对,有道理。但出现的问题应该是数据丢失,而不会出现客户端死机的现象呀
对,有道理。但出现的问题应该是数据丢失,而不会出现客户端死机的现象呀
#16
这种问题很难说出现在什么地方,我也编过相关的程序,
容量比较小的时候没有什么问题,容量大的时候就莫名其妙第出现一些问题,
内存泄漏啊,非法操作啊。而我用BoundsChecker检查是没有内存泄漏的!
你可以Trace一些数据出来,看看到底是哪儿出了问题。你现在的问题只是表象,
你自己还不知道问题究竟出现在什么地方。从容量较小的角度看,你的程序也许根本就没有问题。你现在首先需要确定问题出现在什么地方。
容量比较小的时候没有什么问题,容量大的时候就莫名其妙第出现一些问题,
内存泄漏啊,非法操作啊。而我用BoundsChecker检查是没有内存泄漏的!
你可以Trace一些数据出来,看看到底是哪儿出了问题。你现在的问题只是表象,
你自己还不知道问题究竟出现在什么地方。从容量较小的角度看,你的程序也许根本就没有问题。你现在首先需要确定问题出现在什么地方。
#17
to Lchaos(nicky):
对,如您所说,我现在愁的就是不知道什么地方出现问题。
我测试过MSND的chatsvr例子,它的程序也不行,客户端以5毫秒发送大于4096字节的数据时,一会儿就当机了。
另外,我在接受数据的循环中加入Sleep(5)后,就不会出现客户端死机的现象。我不明白这个语句到底起了什么作用???
对,如您所说,我现在愁的就是不知道什么地方出现问题。
我测试过MSND的chatsvr例子,它的程序也不行,客户端以5毫秒发送大于4096字节的数据时,一会儿就当机了。
另外,我在接受数据的循环中加入Sleep(5)后,就不会出现客户端死机的现象。我不明白这个语句到底起了什么作用???
#18
I think you can:
1. make certain that how many packages has client sent, and how many packages has server received.
2. Where did the program fail? you can trace to a file.
3. for CSocket, it can use Send(..) to send data, yet it doesn't do like that sendDataWait(...). sure, if you want to develop high performance applications, you'd better write your own communication module.
4. i don't know the function of Sleep(5) too. yet i think you can first find where has come the problem.
1. make certain that how many packages has client sent, and how many packages has server received.
2. Where did the program fail? you can trace to a file.
3. for CSocket, it can use Send(..) to send data, yet it doesn't do like that sendDataWait(...). sure, if you want to develop high performance applications, you'd better write your own communication module.
4. i don't know the function of Sleep(5) too. yet i think you can first find where has come the problem.
#19
帖子这么快就看不见,csdn人气真是旺呀。
顶!
顶!
#20
为什么不用 CAsyncSocket??
#21
default情况下windows的socket是以非阻塞形式发送的,也就是说send以后马上返回,具体的发送是windows自己控制的,你发送量很大很频繁,当然会把windows这样的狗屁东西干死,linux下就不会出现这种情况,所以解决办法是:
不能用OnTimer那样的发送方式,用循环,
socket设置成阻塞的,这样只有发送完了send才返回,
不能用OnTimer那样的发送方式,用循环,
socket设置成阻塞的,这样只有发送完了send才返回,
#22
在MCF的CAsyncSocket中有这么一段代码,觉得有点怪怪的。
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
Count++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
Count++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
#23
拷错了
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
nCount++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
nCount++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
#24
嗯,不奇怪,是看错了。
#25
1.缓冲区可能有问题,可以用Winsock中的函数先取回底层缓冲区大小;
2。我还是认为定时5毫秒并不可靠,你最好在发送完成的消息或事件到达时再发送下一个数据块。
3。至于Sleep(5)会使客户端死机的问题,我想问一下你是否使用了多线程?在多线程的情况下会出现这种情况,Sleep会改变线程的执行序。
2。我还是认为定时5毫秒并不可靠,你最好在发送完成的消息或事件到达时再发送下一个数据块。
3。至于Sleep(5)会使客户端死机的问题,我想问一下你是否使用了多线程?在多线程的情况下会出现这种情况,Sleep会改变线程的执行序。
#26
嗯,不奇怪,是看错了。
#27
to:"没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机"
如数据没有写出去被冲了,那么套接就会出错,也就是下一个包它根本就发不出去了。接收也是一样的。
用阻塞方式,不要用Sleep()那对性能很影响。还要有足够大的套接字缓冲区,默认只有8K大,你根本就不能发大于8K的包,因为send()和recv()只是做拷贝的工作。
如数据没有写出去被冲了,那么套接就会出错,也就是下一个包它根本就发不出去了。接收也是一样的。
用阻塞方式,不要用Sleep()那对性能很影响。还要有足够大的套接字缓冲区,默认只有8K大,你根本就不能发大于8K的包,因为send()和recv()只是做拷贝的工作。
#28
to bbasd88:
现在测试的情况是这样的:
1、当我用了Sleep(x),发送30K的数据都可以正常工作。没有加时,也可以发一小段时间。我想如果数据包大于TCP/IP的缓存可能会影响性能,但应该不会出现问题(如果程序处理得当的话)。
2、当客户端出现死机时,我把服务端的给停了后,客户端马上就活过来了,并提示最后两个数据报发送不成功。看来即使数据发送不出去,socket仍是有效的。
现在测试的情况是这样的:
1、当我用了Sleep(x),发送30K的数据都可以正常工作。没有加时,也可以发一小段时间。我想如果数据包大于TCP/IP的缓存可能会影响性能,但应该不会出现问题(如果程序处理得当的话)。
2、当客户端出现死机时,我把服务端的给停了后,客户端马上就活过来了,并提示最后两个数据报发送不成功。看来即使数据发送不出去,socket仍是有效的。
#29
我以前测试的时候,没有出现过这样的问题,今天到单位现场去调试,出现这样的错误消息框,Socket Notification Sink ,还说什么,指针所指的内存不能为read,我都不知道为什么会出现这样的问题,请教!
#30
to waterdrop31:
我没碰过这种问题,指针前面我一般都用ASSERT判断。
我没碰过这种问题,指针前面我一般都用ASSERT判断。
#31
to waterdrop31:
今天我看了一下CSocket及CAsyncSocket的源码,发现如果把CArchive的缓存设成与TCP/IP的缓存一样,即8K,情况就会好一点, CArchive默认的缓存是4096。现在我用10K的数据可以发5万个数据包,但偶尔还是会出现死机现象。
今天我看了一下CSocket及CAsyncSocket的源码,发现如果把CArchive的缓存设成与TCP/IP的缓存一样,即8K,情况就会好一点, CArchive默认的缓存是4096。现在我用10K的数据可以发5万个数据包,但偶尔还是会出现死机现象。
#32
vtable9999,你有oicq吗?我可以直接跟你聊天香你请教一下码?
如何设置CArchive的缓存?
如何设置CArchive的缓存?
#33
6628336
or
vtable9999@msn.com
or
vtable9999@msn.com
#34
经过努力,问题好像解决了,但不明原因所在。明天继续
#35
你好!如何得分?
#36
to vtable9999,问题如何解决的呢?不吝赐教呀
#37
to waterdrop21:
方法在你那不知行不行得通,你可以试试。
我发送的数据是一个结构体CMsg,开始时在每个CMsg::Serialize后面都有一个Flush操作,当数据大于4096,在Server端会产生多个OnReceive事件,而且由于CSocketFile的内部原因,有许多OnReceive有无效的。现在我把那个Flush去掉,只是在最后一次发送时用一下Flush操作。
另:我在CMsg有一个Write函数,所以即使在Serialize后没有调用Flush数据还是可以发送出去。如果你的写数据都是用<<的话,那数据开始是不发的,只能等CArchieve的缓存满了以后才会被发送。
方法在你那不知行不行得通,你可以试试。
我发送的数据是一个结构体CMsg,开始时在每个CMsg::Serialize后面都有一个Flush操作,当数据大于4096,在Server端会产生多个OnReceive事件,而且由于CSocketFile的内部原因,有许多OnReceive有无效的。现在我把那个Flush去掉,只是在最后一次发送时用一下Flush操作。
另:我在CMsg有一个Write函数,所以即使在Serialize后没有调用Flush数据还是可以发送出去。如果你的写数据都是用<<的话,那数据开始是不发的,只能等CArchieve的缓存满了以后才会被发送。
#38
to vtable9999,我不太明白你所说的,可以把你的程序传给我看看码?我想我们可能参考了同一个源程序!谢谢了
#39
我肯定你在传大数据流是没有考虑系统Socket的溢出问题,这也是光学MFC的弊端,只明白怎么用,可是一点都不了解底层。
Socket的Send和Recv操作传大数据时会发生溢出(既丢包现象)
有关内容你可以看看Windows网络编程技术的第7章!!
Send 时用以下的方法:
nLeft=nBytes;
idx=0;
while(nLeft>0)
{
ret=send(s,&sendbuff[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
}
nLeft-=ret;
idx+=ret;
}
recv()的用法同上,如果你看不懂的话,就不要再学VC了,VB比较适合。
不了解底层的VC程序员==VB程序员<<Delph程序员;
真正的高手精通Cpu+操作系统的内核;
VC+ASM===原子蛋!!!!!!!!
Socket的Send和Recv操作传大数据时会发生溢出(既丢包现象)
有关内容你可以看看Windows网络编程技术的第7章!!
Send 时用以下的方法:
nLeft=nBytes;
idx=0;
while(nLeft>0)
{
ret=send(s,&sendbuff[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
}
nLeft-=ret;
idx+=ret;
}
recv()的用法同上,如果你看不懂的话,就不要再学VC了,VB比较适合。
不了解底层的VC程序员==VB程序员<<Delph程序员;
真正的高手精通Cpu+操作系统的内核;
VC+ASM===原子蛋!!!!!!!!
#40
我的程序不但会出现客户端死掉的情况,还会出现vc常见的错误消息框,取消进入调试,则全是二进制代码,这个问题怎么解决呢?
#41
谁与我解惑????????
天哪!!!!!
天哪!!!!!
#42
我对VC不懂,所以只能从底层来分析:
首先你用的是tcp连接吧,现在假设你用的是10M网络,那么你发10K的包相当于16Mbps,这样将超出10M的带宽。如果是4K则为6.4Mbps。很明显10K的包以超出带宽,但TCP协议提供了控制数据流量的机制,所以说TCP协议本身没问题。但CSocket是将TCP协议封装起来了,那么数据先传到CSocket,然后再传给TCP协议,所以我认为是CSocket的问题。要么是CSocket本身的问题,要么就象楼上各位说的是配合的问题。
另:建议编写大数据量的传输直接用底层的协议。
首先你用的是tcp连接吧,现在假设你用的是10M网络,那么你发10K的包相当于16Mbps,这样将超出10M的带宽。如果是4K则为6.4Mbps。很明显10K的包以超出带宽,但TCP协议提供了控制数据流量的机制,所以说TCP协议本身没问题。但CSocket是将TCP协议封装起来了,那么数据先传到CSocket,然后再传给TCP协议,所以我认为是CSocket的问题。要么是CSocket本身的问题,要么就象楼上各位说的是配合的问题。
另:建议编写大数据量的传输直接用底层的协议。
#43
请教各位一个问题,如果我把一个大的数据包分开传输,就会有多个小的数据包,那么就出现每个数据包小了,但是传输频率快了,那么,传送大数据包但频率慢和传送小数据包但频率快相比,那种方式更合理呢?
#44
to waterdrop31(水滴):
关键看你的应用,如果是要将大量的数据传过去且不能丢失,当然是传送大数据包但频率慢合理。但如果是有实时性方面的要求,则是传送小数据包但频率快合理了。
关键看你的应用,如果是要将大量的数据传过去且不能丢失,当然是传送大数据包但频率慢合理。但如果是有实时性方面的要求,则是传送小数据包但频率快合理了。
#45
to wwwunix(木易):
我测试是在同一台机器上,难道也会有10M带宽限制
我测试是在同一台机器上,难道也会有10M带宽限制
#46
建议用API
#47
VC组的兄弟们怎么了,这个问题难道都说得不伦不类?
to wwwunix(木易):
我认为你的想法肯定不对!!!
那么你发10K的包相当于16Mbps 你是如何算来的?我不理解了。包可以比较大,但和带宽并无必然联系吧,别忘了,这里的是TCP包(特别请注意)
如果用别的framwork或许我能帮上忙,但MFC这个我就没有办法了.我的代理服务程序,网关程序从来就没有因为数据量大而死过(包括>20M以上),10Mbit局域网可以轻松上900KBytes.我用的是BCB的 TServerSocket(相当于CAsyncSocket)数据包大过8K是比较常见的。
我不认为这是CSocket的问题。但是因为我不熟悉CSocket因此我不敢妄自评论这个类。
我的QQ 28246466 vtable9999(肝肝肝肝) 我打算请教一下CSocket
to wwwunix(木易):
我认为你的想法肯定不对!!!
那么你发10K的包相当于16Mbps 你是如何算来的?我不理解了。包可以比较大,但和带宽并无必然联系吧,别忘了,这里的是TCP包(特别请注意)
如果用别的framwork或许我能帮上忙,但MFC这个我就没有办法了.我的代理服务程序,网关程序从来就没有因为数据量大而死过(包括>20M以上),10Mbit局域网可以轻松上900KBytes.我用的是BCB的 TServerSocket(相当于CAsyncSocket)数据包大过8K是比较常见的。
我不认为这是CSocket的问题。但是因为我不熟悉CSocket因此我不敢妄自评论这个类。
我的QQ 28246466 vtable9999(肝肝肝肝) 我打算请教一下CSocket
#48
to redpower(常宁):
他是每5ms发一个10K的包,那么每秒发200个包,则每秒要传输的数据为:200*10K*8=16Mbit。所以为16Mbps。
to vtable9999(肝肝肝肝):
有没有限制要看具体的TCP/IP的实现。一般大的数据首先被分成2048字节的多个蔟,然后添加IP头和TCP头,再送到相应的网络接口输出函数。网络接口函数再加上底层协议头,并根据自己的MTU将数据进一步分成数据帧来传输。在这个过程中层与层之间传递数据时不是copy,而是传递相应的地址指针,以提高效率。另:底层的TCP协议是不会有问题的,所以还是上层的原因。
他是每5ms发一个10K的包,那么每秒发200个包,则每秒要传输的数据为:200*10K*8=16Mbit。所以为16Mbps。
to vtable9999(肝肝肝肝):
有没有限制要看具体的TCP/IP的实现。一般大的数据首先被分成2048字节的多个蔟,然后添加IP头和TCP头,再送到相应的网络接口输出函数。网络接口函数再加上底层协议头,并根据自己的MTU将数据进一步分成数据帧来传输。在这个过程中层与层之间传递数据时不是copy,而是传递相应的地址指针,以提高效率。另:底层的TCP协议是不会有问题的,所以还是上层的原因。
#49
10M是这样算出来的吧
10,000 * (1000 / 5) * 8 = 16,000,000 bit
#50
我觉得应该是CSocket的问题,它实现的流程和一般用CAsyncSocket的流程不一样,但我不明白出问题的原因。
基于消息的CAsyncSocket一般是这样:
OnReceive()
{
TCHAR szBuff[1024];
recv(..., szBuff, 1024);
// 如果要接受的数据超过1024,则在下一次OnReceive再接受
}
而在CSocket中是这样的:
OnReceive()
{
CSocketFile::read(...);
// 它要将数据全部读取完了才退出
// 如果数据超过8096字节,实现上是会有多个OnReceive消息,
// 在CSocket这个实现中,只有一个OnRceive是有效的,其它的
// 都滞留在消息队列中。只有当read()方法退出以后,才继续
// dispatch. 这些消息在CSocket里被forward到自己的CSocket继承类
// 前会用IOCtl(FIONRAD)检查,结果都为0,所以不会被继承类
// 接受到。
}
我很怀疑是有太多的OnReceive事件滞留在队列中,才导致client死机的,但无法证实。
我这边的问题其实基本上已经解决,之所以还在寻根问低,是因为我并不认为M$实现CSocket仅仅是为了让初学者能容易使用winsock。如果要用CAsyncSocket实现一个结构体的传送,一个比较安全、健壮的方案基本上要做与CSocket相同的工作,它有的问题也许我们也会碰到。
基于消息的CAsyncSocket一般是这样:
OnReceive()
{
TCHAR szBuff[1024];
recv(..., szBuff, 1024);
// 如果要接受的数据超过1024,则在下一次OnReceive再接受
}
而在CSocket中是这样的:
OnReceive()
{
CSocketFile::read(...);
// 它要将数据全部读取完了才退出
// 如果数据超过8096字节,实现上是会有多个OnReceive消息,
// 在CSocket这个实现中,只有一个OnRceive是有效的,其它的
// 都滞留在消息队列中。只有当read()方法退出以后,才继续
// dispatch. 这些消息在CSocket里被forward到自己的CSocket继承类
// 前会用IOCtl(FIONRAD)检查,结果都为0,所以不会被继承类
// 接受到。
}
我很怀疑是有太多的OnReceive事件滞留在队列中,才导致client死机的,但无法证实。
我这边的问题其实基本上已经解决,之所以还在寻根问低,是因为我并不认为M$实现CSocket仅仅是为了让初学者能容易使用winsock。如果要用CAsyncSocket实现一个结构体的传送,一个比较安全、健壮的方案基本上要做与CSocket相同的工作,它有的问题也许我们也会碰到。
#1
我觉得你的问题都是因为CArchive和CSocket的联合使用的问题,我作过类似的测试,不过是用的SOCKET2。0 API函数,发送100MB的数据包都没有问题,1000MB的时候就出错了~~~
我不太喜欢那样用SOCKET,个人建议~~~
我不太喜欢那样用SOCKET,个人建议~~~
#2
是啊,为什么要使用CSocket呢?呵呵。
to wlrwx,1000MB的数据包? 一个包1000MB?不会吧。
to wlrwx,1000MB的数据包? 一个包1000MB?不会吧。
#3
socket client以5毫秒为间隔?
你能保证5毫秒内数据都能发出去吗???
你能保证5毫秒内数据都能发出去吗???
#4
lanfan说的有理,有可能会有包还没发出就被新来的包冲掉了,接受时也一样。
#5
to wlrwx():
CArchive与CSocket联合使用的问题能不能详细说说??
to neccui(PPC):
我也不喜欢用CSocket,只是有一段现成的代码是用CSocket的。为了赶时间,如果可以满足性能想将就一下。
to lanfan:
没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机。
CArchive与CSocket联合使用的问题能不能详细说说??
to neccui(PPC):
我也不喜欢用CSocket,只是有一段现成的代码是用CSocket的。为了赶时间,如果可以满足性能想将就一下。
to lanfan:
没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机。
#6
我推!!!!!!!!!!!!
#7
才9点,怎么就没人了???难道程序员也泡妞???????????
#8
关注,vtable9999,我和你用的方法一样,CSocket和CArchive联合传送数据,
但是我传数据间隔的时间不定,通常十秒3个数据包,每个包50k左右,多的时候,连续不断的传200多个数据包,每个包50k.
我的程序也是会出现客户端程序死机的情况,请教!
但是我传数据间隔的时间不定,通常十秒3个数据包,每个包50k左右,多的时候,连续不断的传200多个数据包,每个包50k.
我的程序也是会出现客户端程序死机的情况,请教!
#9
to waterdrop31(水滴): 帮我推推,一定要把问题解决了
#10
TCP协议本身的缓冲是有限的,默认是48K. 所以发送数据最好在一个:
while(1)
{
send();
......
这样,即使缓冲满了,send()也会自动挂起。
while(1)
{
send();
......
这样,即使缓冲满了,send()也会自动挂起。
#11
试一试这段Code, 我想应当确定数据报已经被送出:
for(DWORD t = GetTickCount() +300; (bytes < sizeof(msg) && GetTickCount() < t);)
{
bytesent = send(msocket, (const char*)&msg+bytes, sizeof(msg)-bytes, 0);
if(SOCKET_ERROR == rc)
{
err = WSAGetLastError();
if(err != WSAEWOULDBLOCK)
{
return -1; // TODO: log error
}
else
Sleep(1); // take a break
}
else
{
bytes += bytesent;
}
}
for(DWORD t = GetTickCount() +300; (bytes < sizeof(msg) && GetTickCount() < t);)
{
bytesent = send(msocket, (const char*)&msg+bytes, sizeof(msg)-bytes, 0);
if(SOCKET_ERROR == rc)
{
err = WSAGetLastError();
if(err != WSAEWOULDBLOCK)
{
return -1; // TODO: log error
}
else
Sleep(1); // take a break
}
else
{
bytes += bytesent;
}
}
#12
ok, 马上汇报测试结果
#13
糟,没法测试
#14
yes, for the OS, there is a sending buffer and a receiving buffer,
and the buffer size is fixed, if you send too much data frequently,
you may fail to send the data, for the receiving part, it is the same. so in communication program, you'd write some functions such as: sendDataWait(...), sendDataTimeout(...), recvDataWait(...), recvDataTimeout(...).
eg: for sendDataWait(...), if the sending buffer is full, then you call select() function to test if it is ok to send data, you may find that no data can be sent, at this time, you have to wait.
for the timeout function, it is only to not to block. if i can't send the data in a certain time, maybe the network is not reliable.
and the buffer size is fixed, if you send too much data frequently,
you may fail to send the data, for the receiving part, it is the same. so in communication program, you'd write some functions such as: sendDataWait(...), sendDataTimeout(...), recvDataWait(...), recvDataTimeout(...).
eg: for sendDataWait(...), if the sending buffer is full, then you call select() function to test if it is ok to send data, you may find that no data can be sent, at this time, you have to wait.
for the timeout function, it is only to not to block. if i can't send the data in a certain time, maybe the network is not reliable.
#15
to Lchaos(nicky):
对,有道理。但出现的问题应该是数据丢失,而不会出现客户端死机的现象呀
对,有道理。但出现的问题应该是数据丢失,而不会出现客户端死机的现象呀
#16
这种问题很难说出现在什么地方,我也编过相关的程序,
容量比较小的时候没有什么问题,容量大的时候就莫名其妙第出现一些问题,
内存泄漏啊,非法操作啊。而我用BoundsChecker检查是没有内存泄漏的!
你可以Trace一些数据出来,看看到底是哪儿出了问题。你现在的问题只是表象,
你自己还不知道问题究竟出现在什么地方。从容量较小的角度看,你的程序也许根本就没有问题。你现在首先需要确定问题出现在什么地方。
容量比较小的时候没有什么问题,容量大的时候就莫名其妙第出现一些问题,
内存泄漏啊,非法操作啊。而我用BoundsChecker检查是没有内存泄漏的!
你可以Trace一些数据出来,看看到底是哪儿出了问题。你现在的问题只是表象,
你自己还不知道问题究竟出现在什么地方。从容量较小的角度看,你的程序也许根本就没有问题。你现在首先需要确定问题出现在什么地方。
#17
to Lchaos(nicky):
对,如您所说,我现在愁的就是不知道什么地方出现问题。
我测试过MSND的chatsvr例子,它的程序也不行,客户端以5毫秒发送大于4096字节的数据时,一会儿就当机了。
另外,我在接受数据的循环中加入Sleep(5)后,就不会出现客户端死机的现象。我不明白这个语句到底起了什么作用???
对,如您所说,我现在愁的就是不知道什么地方出现问题。
我测试过MSND的chatsvr例子,它的程序也不行,客户端以5毫秒发送大于4096字节的数据时,一会儿就当机了。
另外,我在接受数据的循环中加入Sleep(5)后,就不会出现客户端死机的现象。我不明白这个语句到底起了什么作用???
#18
I think you can:
1. make certain that how many packages has client sent, and how many packages has server received.
2. Where did the program fail? you can trace to a file.
3. for CSocket, it can use Send(..) to send data, yet it doesn't do like that sendDataWait(...). sure, if you want to develop high performance applications, you'd better write your own communication module.
4. i don't know the function of Sleep(5) too. yet i think you can first find where has come the problem.
1. make certain that how many packages has client sent, and how many packages has server received.
2. Where did the program fail? you can trace to a file.
3. for CSocket, it can use Send(..) to send data, yet it doesn't do like that sendDataWait(...). sure, if you want to develop high performance applications, you'd better write your own communication module.
4. i don't know the function of Sleep(5) too. yet i think you can first find where has come the problem.
#19
帖子这么快就看不见,csdn人气真是旺呀。
顶!
顶!
#20
为什么不用 CAsyncSocket??
#21
default情况下windows的socket是以非阻塞形式发送的,也就是说send以后马上返回,具体的发送是windows自己控制的,你发送量很大很频繁,当然会把windows这样的狗屁东西干死,linux下就不会出现这种情况,所以解决办法是:
不能用OnTimer那样的发送方式,用循环,
socket设置成阻塞的,这样只有发送完了send才返回,
不能用OnTimer那样的发送方式,用循环,
socket设置成阻塞的,这样只有发送完了send才返回,
#22
在MCF的CAsyncSocket中有这么一段代码,觉得有点怪怪的。
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
Count++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
Count++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
#23
拷错了
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
nCount++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
int nCount;
if (pState->m_pmapDeadSockets->Lookup((void*)hSocket, (void*&)nCount))
nCount++;
else
nCount = 1;
pState->m_pmapDeadSockets->SetAt((void*)hSocket, (void*)nCount);
#24
嗯,不奇怪,是看错了。
#25
1.缓冲区可能有问题,可以用Winsock中的函数先取回底层缓冲区大小;
2。我还是认为定时5毫秒并不可靠,你最好在发送完成的消息或事件到达时再发送下一个数据块。
3。至于Sleep(5)会使客户端死机的问题,我想问一下你是否使用了多线程?在多线程的情况下会出现这种情况,Sleep会改变线程的执行序。
2。我还是认为定时5毫秒并不可靠,你最好在发送完成的消息或事件到达时再发送下一个数据块。
3。至于Sleep(5)会使客户端死机的问题,我想问一下你是否使用了多线程?在多线程的情况下会出现这种情况,Sleep会改变线程的执行序。
#26
嗯,不奇怪,是看错了。
#27
to:"没有检查过,在同台机器下5毫秒应该够长了吧。另外,即使是数据没写出去,被冲掉了,客户端应该不会出现死机"
如数据没有写出去被冲了,那么套接就会出错,也就是下一个包它根本就发不出去了。接收也是一样的。
用阻塞方式,不要用Sleep()那对性能很影响。还要有足够大的套接字缓冲区,默认只有8K大,你根本就不能发大于8K的包,因为send()和recv()只是做拷贝的工作。
如数据没有写出去被冲了,那么套接就会出错,也就是下一个包它根本就发不出去了。接收也是一样的。
用阻塞方式,不要用Sleep()那对性能很影响。还要有足够大的套接字缓冲区,默认只有8K大,你根本就不能发大于8K的包,因为send()和recv()只是做拷贝的工作。
#28
to bbasd88:
现在测试的情况是这样的:
1、当我用了Sleep(x),发送30K的数据都可以正常工作。没有加时,也可以发一小段时间。我想如果数据包大于TCP/IP的缓存可能会影响性能,但应该不会出现问题(如果程序处理得当的话)。
2、当客户端出现死机时,我把服务端的给停了后,客户端马上就活过来了,并提示最后两个数据报发送不成功。看来即使数据发送不出去,socket仍是有效的。
现在测试的情况是这样的:
1、当我用了Sleep(x),发送30K的数据都可以正常工作。没有加时,也可以发一小段时间。我想如果数据包大于TCP/IP的缓存可能会影响性能,但应该不会出现问题(如果程序处理得当的话)。
2、当客户端出现死机时,我把服务端的给停了后,客户端马上就活过来了,并提示最后两个数据报发送不成功。看来即使数据发送不出去,socket仍是有效的。
#29
我以前测试的时候,没有出现过这样的问题,今天到单位现场去调试,出现这样的错误消息框,Socket Notification Sink ,还说什么,指针所指的内存不能为read,我都不知道为什么会出现这样的问题,请教!
#30
to waterdrop31:
我没碰过这种问题,指针前面我一般都用ASSERT判断。
我没碰过这种问题,指针前面我一般都用ASSERT判断。
#31
to waterdrop31:
今天我看了一下CSocket及CAsyncSocket的源码,发现如果把CArchive的缓存设成与TCP/IP的缓存一样,即8K,情况就会好一点, CArchive默认的缓存是4096。现在我用10K的数据可以发5万个数据包,但偶尔还是会出现死机现象。
今天我看了一下CSocket及CAsyncSocket的源码,发现如果把CArchive的缓存设成与TCP/IP的缓存一样,即8K,情况就会好一点, CArchive默认的缓存是4096。现在我用10K的数据可以发5万个数据包,但偶尔还是会出现死机现象。
#32
vtable9999,你有oicq吗?我可以直接跟你聊天香你请教一下码?
如何设置CArchive的缓存?
如何设置CArchive的缓存?
#33
6628336
or
vtable9999@msn.com
or
vtable9999@msn.com
#34
经过努力,问题好像解决了,但不明原因所在。明天继续
#35
你好!如何得分?
#36
to vtable9999,问题如何解决的呢?不吝赐教呀
#37
to waterdrop21:
方法在你那不知行不行得通,你可以试试。
我发送的数据是一个结构体CMsg,开始时在每个CMsg::Serialize后面都有一个Flush操作,当数据大于4096,在Server端会产生多个OnReceive事件,而且由于CSocketFile的内部原因,有许多OnReceive有无效的。现在我把那个Flush去掉,只是在最后一次发送时用一下Flush操作。
另:我在CMsg有一个Write函数,所以即使在Serialize后没有调用Flush数据还是可以发送出去。如果你的写数据都是用<<的话,那数据开始是不发的,只能等CArchieve的缓存满了以后才会被发送。
方法在你那不知行不行得通,你可以试试。
我发送的数据是一个结构体CMsg,开始时在每个CMsg::Serialize后面都有一个Flush操作,当数据大于4096,在Server端会产生多个OnReceive事件,而且由于CSocketFile的内部原因,有许多OnReceive有无效的。现在我把那个Flush去掉,只是在最后一次发送时用一下Flush操作。
另:我在CMsg有一个Write函数,所以即使在Serialize后没有调用Flush数据还是可以发送出去。如果你的写数据都是用<<的话,那数据开始是不发的,只能等CArchieve的缓存满了以后才会被发送。
#38
to vtable9999,我不太明白你所说的,可以把你的程序传给我看看码?我想我们可能参考了同一个源程序!谢谢了
#39
我肯定你在传大数据流是没有考虑系统Socket的溢出问题,这也是光学MFC的弊端,只明白怎么用,可是一点都不了解底层。
Socket的Send和Recv操作传大数据时会发生溢出(既丢包现象)
有关内容你可以看看Windows网络编程技术的第7章!!
Send 时用以下的方法:
nLeft=nBytes;
idx=0;
while(nLeft>0)
{
ret=send(s,&sendbuff[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
}
nLeft-=ret;
idx+=ret;
}
recv()的用法同上,如果你看不懂的话,就不要再学VC了,VB比较适合。
不了解底层的VC程序员==VB程序员<<Delph程序员;
真正的高手精通Cpu+操作系统的内核;
VC+ASM===原子蛋!!!!!!!!
Socket的Send和Recv操作传大数据时会发生溢出(既丢包现象)
有关内容你可以看看Windows网络编程技术的第7章!!
Send 时用以下的方法:
nLeft=nBytes;
idx=0;
while(nLeft>0)
{
ret=send(s,&sendbuff[idx],nLeft,0);
if(ret==SOCKET_ERROR)
{
}
nLeft-=ret;
idx+=ret;
}
recv()的用法同上,如果你看不懂的话,就不要再学VC了,VB比较适合。
不了解底层的VC程序员==VB程序员<<Delph程序员;
真正的高手精通Cpu+操作系统的内核;
VC+ASM===原子蛋!!!!!!!!
#40
我的程序不但会出现客户端死掉的情况,还会出现vc常见的错误消息框,取消进入调试,则全是二进制代码,这个问题怎么解决呢?
#41
谁与我解惑????????
天哪!!!!!
天哪!!!!!
#42
我对VC不懂,所以只能从底层来分析:
首先你用的是tcp连接吧,现在假设你用的是10M网络,那么你发10K的包相当于16Mbps,这样将超出10M的带宽。如果是4K则为6.4Mbps。很明显10K的包以超出带宽,但TCP协议提供了控制数据流量的机制,所以说TCP协议本身没问题。但CSocket是将TCP协议封装起来了,那么数据先传到CSocket,然后再传给TCP协议,所以我认为是CSocket的问题。要么是CSocket本身的问题,要么就象楼上各位说的是配合的问题。
另:建议编写大数据量的传输直接用底层的协议。
首先你用的是tcp连接吧,现在假设你用的是10M网络,那么你发10K的包相当于16Mbps,这样将超出10M的带宽。如果是4K则为6.4Mbps。很明显10K的包以超出带宽,但TCP协议提供了控制数据流量的机制,所以说TCP协议本身没问题。但CSocket是将TCP协议封装起来了,那么数据先传到CSocket,然后再传给TCP协议,所以我认为是CSocket的问题。要么是CSocket本身的问题,要么就象楼上各位说的是配合的问题。
另:建议编写大数据量的传输直接用底层的协议。
#43
请教各位一个问题,如果我把一个大的数据包分开传输,就会有多个小的数据包,那么就出现每个数据包小了,但是传输频率快了,那么,传送大数据包但频率慢和传送小数据包但频率快相比,那种方式更合理呢?
#44
to waterdrop31(水滴):
关键看你的应用,如果是要将大量的数据传过去且不能丢失,当然是传送大数据包但频率慢合理。但如果是有实时性方面的要求,则是传送小数据包但频率快合理了。
关键看你的应用,如果是要将大量的数据传过去且不能丢失,当然是传送大数据包但频率慢合理。但如果是有实时性方面的要求,则是传送小数据包但频率快合理了。
#45
to wwwunix(木易):
我测试是在同一台机器上,难道也会有10M带宽限制
我测试是在同一台机器上,难道也会有10M带宽限制
#46
建议用API
#47
VC组的兄弟们怎么了,这个问题难道都说得不伦不类?
to wwwunix(木易):
我认为你的想法肯定不对!!!
那么你发10K的包相当于16Mbps 你是如何算来的?我不理解了。包可以比较大,但和带宽并无必然联系吧,别忘了,这里的是TCP包(特别请注意)
如果用别的framwork或许我能帮上忙,但MFC这个我就没有办法了.我的代理服务程序,网关程序从来就没有因为数据量大而死过(包括>20M以上),10Mbit局域网可以轻松上900KBytes.我用的是BCB的 TServerSocket(相当于CAsyncSocket)数据包大过8K是比较常见的。
我不认为这是CSocket的问题。但是因为我不熟悉CSocket因此我不敢妄自评论这个类。
我的QQ 28246466 vtable9999(肝肝肝肝) 我打算请教一下CSocket
to wwwunix(木易):
我认为你的想法肯定不对!!!
那么你发10K的包相当于16Mbps 你是如何算来的?我不理解了。包可以比较大,但和带宽并无必然联系吧,别忘了,这里的是TCP包(特别请注意)
如果用别的framwork或许我能帮上忙,但MFC这个我就没有办法了.我的代理服务程序,网关程序从来就没有因为数据量大而死过(包括>20M以上),10Mbit局域网可以轻松上900KBytes.我用的是BCB的 TServerSocket(相当于CAsyncSocket)数据包大过8K是比较常见的。
我不认为这是CSocket的问题。但是因为我不熟悉CSocket因此我不敢妄自评论这个类。
我的QQ 28246466 vtable9999(肝肝肝肝) 我打算请教一下CSocket
#48
to redpower(常宁):
他是每5ms发一个10K的包,那么每秒发200个包,则每秒要传输的数据为:200*10K*8=16Mbit。所以为16Mbps。
to vtable9999(肝肝肝肝):
有没有限制要看具体的TCP/IP的实现。一般大的数据首先被分成2048字节的多个蔟,然后添加IP头和TCP头,再送到相应的网络接口输出函数。网络接口函数再加上底层协议头,并根据自己的MTU将数据进一步分成数据帧来传输。在这个过程中层与层之间传递数据时不是copy,而是传递相应的地址指针,以提高效率。另:底层的TCP协议是不会有问题的,所以还是上层的原因。
他是每5ms发一个10K的包,那么每秒发200个包,则每秒要传输的数据为:200*10K*8=16Mbit。所以为16Mbps。
to vtable9999(肝肝肝肝):
有没有限制要看具体的TCP/IP的实现。一般大的数据首先被分成2048字节的多个蔟,然后添加IP头和TCP头,再送到相应的网络接口输出函数。网络接口函数再加上底层协议头,并根据自己的MTU将数据进一步分成数据帧来传输。在这个过程中层与层之间传递数据时不是copy,而是传递相应的地址指针,以提高效率。另:底层的TCP协议是不会有问题的,所以还是上层的原因。
#49
10M是这样算出来的吧
10,000 * (1000 / 5) * 8 = 16,000,000 bit
#50
我觉得应该是CSocket的问题,它实现的流程和一般用CAsyncSocket的流程不一样,但我不明白出问题的原因。
基于消息的CAsyncSocket一般是这样:
OnReceive()
{
TCHAR szBuff[1024];
recv(..., szBuff, 1024);
// 如果要接受的数据超过1024,则在下一次OnReceive再接受
}
而在CSocket中是这样的:
OnReceive()
{
CSocketFile::read(...);
// 它要将数据全部读取完了才退出
// 如果数据超过8096字节,实现上是会有多个OnReceive消息,
// 在CSocket这个实现中,只有一个OnRceive是有效的,其它的
// 都滞留在消息队列中。只有当read()方法退出以后,才继续
// dispatch. 这些消息在CSocket里被forward到自己的CSocket继承类
// 前会用IOCtl(FIONRAD)检查,结果都为0,所以不会被继承类
// 接受到。
}
我很怀疑是有太多的OnReceive事件滞留在队列中,才导致client死机的,但无法证实。
我这边的问题其实基本上已经解决,之所以还在寻根问低,是因为我并不认为M$实现CSocket仅仅是为了让初学者能容易使用winsock。如果要用CAsyncSocket实现一个结构体的传送,一个比较安全、健壮的方案基本上要做与CSocket相同的工作,它有的问题也许我们也会碰到。
基于消息的CAsyncSocket一般是这样:
OnReceive()
{
TCHAR szBuff[1024];
recv(..., szBuff, 1024);
// 如果要接受的数据超过1024,则在下一次OnReceive再接受
}
而在CSocket中是这样的:
OnReceive()
{
CSocketFile::read(...);
// 它要将数据全部读取完了才退出
// 如果数据超过8096字节,实现上是会有多个OnReceive消息,
// 在CSocket这个实现中,只有一个OnRceive是有效的,其它的
// 都滞留在消息队列中。只有当read()方法退出以后,才继续
// dispatch. 这些消息在CSocket里被forward到自己的CSocket继承类
// 前会用IOCtl(FIONRAD)检查,结果都为0,所以不会被继承类
// 接受到。
}
我很怀疑是有太多的OnReceive事件滞留在队列中,才导致client死机的,但无法证实。
我这边的问题其实基本上已经解决,之所以还在寻根问低,是因为我并不认为M$实现CSocket仅仅是为了让初学者能容易使用winsock。如果要用CAsyncSocket实现一个结构体的传送,一个比较安全、健壮的方案基本上要做与CSocket相同的工作,它有的问题也许我们也会碰到。