继续请Socket高手指点,为什么我的Socket每次接收和发送不能达到64K字节???

hecCIBN 2002-06-19 12:04:09
我用的是棉线连接的TCP流式socket,如果server端发送64k的数据,我一般都不能全部接收到,而是分几次才能接收到64k。我需要设置什么参数才能解决这个问题啊?
还望高手指点一下。
...全文
446 50 打赏 收藏 转发到动态 举报
写回复
用AI写文章
50 条回复
切换为时间正序
请发表友善的回复…
发表回复
常宁 2002-06-21
  • 打赏
  • 举报
回复
to johnnyxia(flyingheart)
每秒多少个40字节包?
Win2000上,我做的大概能达到10000个/秒以上,具体的我忘了 --异步方式
同步方式好像是小一个数量级大概1000多个,
是服务器方式的TCP
johnnyxia 2002-06-21
  • 打赏
  • 举报
回复
URL没错,我可以上。

对于直接使用socket API的问题,我仍然坚持不要使用C++封装。socket API已经非常精简,我看不出封装一个类能省去多少代码。他反而会增加麻烦。出了问题你还是要跟踪到API一层。但是一种情况下C++的封装能体现它的好处,比如CSockFile,如果使用它可以让某些代码变得灵活。这属于Design Pattern有些跑题。

另外,Win95下block模式效率绝对不低,我做过专门的测试,可以用数据说话。
常宁 2002-06-20
  • 打赏
  • 举报
回复
to limin(我好笨我好困)
对于模型,我们已经探讨过了,单处理器窗体程序通常采用相对高效的WSAAsycnSelect模型。
线程问题:复杂些的Socket服务程序通常采用线程池方式处理客户请求,并不是每个接入都分配线程,有些不需要复杂延时的应用,比如某些网关设置都不需要单独的线程,只要在主线程中就十分高效,而且无论如何在windows下我们还是采用异步方式为好,特别是发送,只有这样才能充分发挥平台优势。
  • 打赏
  • 举报
回复
同意redpower(常宁)的说法。
另外,我也有一个问题,windows下面有5种I/O模型,分别是select、WSAAsyncSelect、事件模型、重叠I/O模型、完成模型,如果我想写一个程序,满足一下要求。
1、我的这个windows程序不限制操作系统,那么完成模型显然不能用。
2、程序本身存在消息循环,而且程序是作为服务器,WSAAsyncSelect用过,可是效果不是很好。
3、如果为每一个接入端都提供一个线程,数量少的话还好,数量一多,效率下降很明显。
我想问一下,这时在模型和线程机制上应该如何选择。
afj 2002-06-20
  • 打赏
  • 举报
回复
up
常宁 2002-06-20
  • 打赏
  • 举报
回复
to steel_de_lee(问题)
阻塞方式在windows下的效率低,但我不认为windows环境同unix特别是BSD的环境相同,因此设计在unix类系统下工作的apache等软件,在windows下工作不应该能达到最佳状态,特别是没有使用Windows的扩展部分。这些软件基本在大多数平台都可以编译,但是在windows下用Select不是一个好的方法。因为有更好的winsocket扩展函数。unix平台中select是唯一的选择,而且这不能说明select在windows下回工作的同样好.
BluePenguin 2002-06-20
  • 打赏
  • 举报
回复
while (m_nBytesSent < m_nBytesBufferSize)
{
int dwBytes;

if ((dwBytes = Send((LPCTSTR)m_sendBuffer + m_nBytesSent,
m_nBytesBufferSize - m_nBytesSent)) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK) break;
else
{
TCHAR szError[256];
wsprintf(szError, "Server Socket failed to send: %d",
GetLastError());
Close();
AfxMessageBox (szError);
}
}
else
{
m_nBytesSent += dwBytes;
}
}
steel_de_lee 2002-06-20
  • 打赏
  • 举报
回复
to redpower

我很想知道你如何测试出Select效率很低的方法,因为Apache等诸多服务器
程序采用Select
jeffchen 2002-06-20
  • 打赏
  • 举报
回复
TCP协议本身就决定了不一定能一次把Server发送的一个数据包接受完毕。操作系统在发送时,会根据实际情况决定是一次发完还是分几次发送。

因此,client在编写的时候要考虑到这种情况。如果使用Block(阻塞)模式,就容易解决,可以等到收到足够的数据,但效率低;如果使用Non-Block(非阻塞)模式,就要对收到的数据进行拼装。
常宁 2002-06-20
  • 打赏
  • 举报
回复
下面的是我以前回答的,顺便贴一下,同上面的对照一下:)

完成端口的优点是可以充分发挥多处理器的优点,在单处理器上使用效果并非很好,因此在单处理器,Windows窗体程序中使用异步消息驱动应该是最好的选择。多处理器时用完成端口,如果不嫌麻烦,单处理器可以用重叠模型。强烈反对使用阻塞方式,同非阻塞相比,阻塞方式效率很低,Select方式的效率我的测试表明很低。另外还是事件模型,如果程序没有消息循环,用事件模型是个好的选择,但是如果存在消息循环,用事件模型就不合适!
MFC的CSocket是一个简单低效的东西相信所有做服务器程序的人都不会采用!CAsyncSocket效率要好些,但是封装十分差,我看不如用API自己写一个类,相比下TServerSocket的效率和封装都很好,但是没有源码,不能移植到VC上。他的效率很高,如果打算做一个高负荷的程序TServerSocket是最好的选择,不过如果选择和这个类,也就选择了Borland C++.TTCPServer很象CSocket,效率不是很好。我不推荐用。TPowerSocket的性能是最差的,而且BUG奇多,强烈反对使用。Indy组件的稳定性不错。但是效率一般,特别是阻塞方式效率较差。VBSocket控件不是一个能用的选择,适用范围很有限。因此我不相信有人会在C++环境下使用这个OCX控件
常宁 2002-06-20
  • 打赏
  • 举报
回复
这是以前我写的,顺便帖上来,同上面的对照一下:)

完成端口的优点是可以充分发挥多处理器的优点,在单处理器上使用效果并非很好,因此在单处理器,Windows窗体程序中使用异步消息驱动应该是最好的选择。多处理器时用完成端口,如果不嫌麻烦,单处理器可以用重叠模型。强烈反对使用阻塞方式,同非阻塞相比,阻塞方式效率很低,Select方式的效率我的测试表明很低。另外还是事件模型,如果程序没有消息循环,用事件模型是个好的选择,但是如果存在消息循环,用事件模型就不合适!
MFC的CSocket是一个简单低效的东西相信所有做服务器程序的人都不会采用!CAsyncSocket效率要好些,但是封装十分差,我看不如用API自己写一个类,相比下TServerSocket的效率和封装都很好,但是没有源码,不能移植到VC上。他的效率很高,如果打算做一个高负荷的程序TServerSocket是最好的选择,不过如果选择和这个类,也就选择了Borland C++.TTCPServer很象CSocket,效率不是很好。我不推荐用。TPowerSocket的性能是最差的,而且BUG奇多,强烈反对使用。Indy组件的稳定性不错。但是效率一般,特别是阻塞方式效率较差。VBSocket控件不是一个能用的选择,适用范围很有限。因此我不相信有人会在C++环境下使用这个OCX控件
常宁 2002-06-20
  • 打赏
  • 举报
回复
to Fairton(飞云)
异步方式可以一次发送但是不代表能一次接收,实际上Windows将这些数据放在缓冲区中(不是socket缓冲区)他的大小是一个有符号整数(如果内存够包括虚拟的可达到2GB),接受方会接受到很多的包,每个包到达的时候都会产生一个接收消息,因此可以将所有的接收消息拼接起来。

to TopLevel()
阻塞方式就是发送,连接,接收时候如果没有完成,不会继续向下执行,除非超时!非阻塞方式(异步方式)可以一次发送2G,阻塞方式一次最多发送Socket发送缓冲区大小的包,这应该是常识!因此我不认为我们的争论有什么意义。了解这个,看伯克里Socket的文章是没有用的,Windows重来都不会简单地遵循一个老的规范而不会进行改进,这不是M$的作风。winSocket本质上是Socket的扩充,他扩充了很多的函数,特别是winsocket2,对于很多环境下它的扩充是革命性的,当然它的思想不可能用在现有的其他系统,比如伯克利的BSD,或是linux,AIX,HP-UX上。Borland为了兼容伯克利socket不得不改变了他的主要的socket类TClientSocket/TServerSocket,而编写的新的Socket实现TTCPSocket/TTCPClient实现,并将低效的阻塞模式设置为标准模式,这主要因为在linux下TClientSocket/TServerSocket不可能正常地同Windows下一样运行!而遵照伯克利的TTCPServer/TTCPClient可以。
hecCIBN 2002-06-20
  • 打赏
  • 举报
回复
问题还没有解决,请大家继续发表讨论
常宁 2002-06-20
  • 打赏
  • 举报
回复
to all
我们是不是讨论有些跑题?

to johnnyxia()
http://tangentsoft.net/wskfaq/
这个站点上不去,是不是写错了。
我不同意你的观点,如果能用封装好的类尽量用,不要动不动就自己编写API程序,这不是好习惯,特别是对于C++这样的开发环境,须知时间有限。
不过我反对用CSocket.其实大家可以参看 DarkMonk(黑心和尚)写的,我认为很有道理,其实用一下别的开发工具很有用,否则有井底之蛙的感觉,对于TCP,VCL封装得确实很好.

to bugz(歪歪)
我们讨论不带偏见,阻塞模式的socket对于Windows来说效率很低!!!
异步socket确实是因为Windows3.x的拙劣的CPU调度技术的产物,但是现在的基于NT技术的异步方式确实要好于基于NT同步方式,别的系统没有提供这样的功能,如果提供,我相信也一定会好于阻塞模式。
johnnyxia 2002-06-20
  • 打赏
  • 举报
回复
http://tangentsoft.net/wskfaq/
强力推荐以上网址。关于不同的模式次份FAQ有详细的论述。

我个人觉得如果量不大,又有UI可以用WSAAsyncSelect()。
没有UI的可以用block模式。在万不得已情况下不要用select(),
尤其是在Windows下。对于量大的,专业级的服务端程序可以用
Overlapped I/O or Completion Port.

另外,直接使用SDK,没有必要MFC的CSocket或其他封装。
bugz 2002-06-20
  • 打赏
  • 举报
回复
异步好么?我不觉得,大家太夸张block模型的消耗了吧,那是16位windows时代的观念啊
DarkMonk 2002-06-20
  • 打赏
  • 举报
回复
用CBuilder或Delphi吧,管它数据量多大,一下子就Send出去了,发送和接收的处理都不用自已做,你要做的告诉它数据在哪、给谁就行了。
hecCIBN 2002-06-19
  • 打赏
  • 举报
回复
to TopLevel() :
你能详细说一下吗?这种情况怎么解决啊?
TopLevel 2002-06-19
  • 打赏
  • 举报
回复
因为在进行数据传递时,有一个缓冲区,每次发送或接受的数据量示此缓冲区的大小而定,如果传输的数据大于此缓冲区,则必须进行多次的发送或接受。
hongyucn 2002-06-19
  • 打赏
  • 举报
回复
还有TCP/IP的底层是一个FIFO。如果写过底层驱动的朋友就了解为什么它收发不一致的原因了!
加载更多回复(30)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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