完成端口接收和发送数据问题

fieldisme 2007-12-11 08:09:53
[size=18px]我想封装一个完成端口类,WSARecv和WSASend函数都有一个参数是WSABUF数组,而数组需要连续的内存,如果我要发送或接收的数据大小不确定,则这个数组长度不确定,不能事先创建数组,是不是每次都要动态创建这个数组,然后从缓冲区链表上取下一个缓冲区把指针赋给数组成员的buf,数据收发完成后又要释放这个数组呢?如果是这样,几千个并发连接时岂不是频繁申请内存又释放,会不会对系统性能带来影响呢?还是有其它更好的方法呢,请高手指点一下。[/size]
...全文
360 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
yongta 2010-06-20
  • 打赏
  • 举报
回复
没有必要一次传一组,一次传一个就好了,.
laowang2 2008-08-23
  • 打赏
  • 举报
回复
upup
fieldisme 2007-12-12
  • 打赏
  • 举报
回复
我的内存是这样管理的:创建一个链表,当需要缓冲区时,检查这个链表是否为空,如果为空则创建一个缓冲区,如果不为空则取下一个结点,缓冲区用完后不释放,直接插入链表中,每次创建的缓冲区是4098个字节。不知道是不是这样管理内存有问题。我没有《windows网络编程》书,只有本《windows网络编程技术》,其中并没有讲如何管理内存池,而我这种内存管理方式决定每个缓冲区的大小是定值。按网上有些文章说的,程序运行之初创建一大块内存,好像可以像你说的那样调整缓冲区大小,不过这也有个问题我不知怎么处理,假设每块内存都使用过了,其中有些小块的内存已处于未用状态,而有些内存还在使用,此时需要一块大内存,所有小块空闲内存之和远大于这一块,但每一小块都不够大,必然取不出这块内存,而事实上此时内存并没用完,也就是说会出现内存资源利用率低的情况,这个问题你是怎么解决的呢
僵哥 2007-12-12
  • 打赏
  • 举报
回复
如果用一个WSABUF,则每次只能投递一个缓冲区,在发送大量数据时,会不会频繁在用户态和核心态之间切换,从而降低性能,既然函数设计的参数是一个数组,我想传递一个数组效率应该更高吧。
===============================
发多个缓冲区块,为什么不扩大发送缓冲区?一个WSABUF,仅仅只是代码一个逻辑数据组,也就是可以实现,你一次提交,多次通知的目的。

使用内存池,需要解决的是重复内存申请/释放的资源消耗。就好比,在家里吃饭,如果都用一次性碗,这个时候是不是有多少人就要买多少次,而为了省去这种麻烦,你就准备了一个橱柜,买上瓷碗,这个时候,加一个人,不足用的时候,再买一个碗,用完之后就放橱柜里面,下次再需要的时候就不需要再去买了。
fieldisme 2007-12-12
  • 打赏
  • 举报
回复
如果用一个WSABUF,则每次只能投递一个缓冲区,在发送大量数据时,会不会频繁在用户态和核心态之间切换,从而降低性能,既然函数设计的参数是一个数组,我想传递一个数组效率应该更高吧。

2楼说的用内存池的方式,指的是缓冲区吧,我说的是指向缓冲区的指针。
僵哥 2007-12-12
  • 打赏
  • 举报
回复
以前曾经使用C++ Builder写过一个,不过当中有很多问题,后来改用Delphi,就直接使用Delphi重写了所有代码。
僵哥 2007-12-12
  • 打赏
  • 举报
回复
不要管它是否数组,在个人业务当中,一个WSABUF,很难满足业务的需求。所以你可以每次使用WSABUF,接收完成(可能是缓冲区满)之后,再重新发起一个。
yuanreid 2007-12-12
  • 打赏
  • 举报
回复
windows网络编程上有完整的例子,这部分是采用内存池的方式实现的。不需要反复申请内存
ydlchina 2007-12-12
  • 打赏
  • 举报
回复
顶顶
fieldisme 2007-12-12
  • 打赏
  • 举报
回复
谢谢僵哥的回答,你说得很有道理,我想了想,觉得一次传输一组不会带来多大的好处,反而使编程更复杂,因为系统不是在所有缓冲区发送完后再发出完成通知,在完成通知到来的时候,还得移动缓冲区指针进行下一次调用,其实传输一组是多余的

再次谢谢僵哥的回答,我准备结贴了,如果各位还有什么要讨论的,请QQ联系。我的QQ791905630,请填入加好友理由,谢谢
僵哥 2007-12-12
  • 打赏
  • 举报
回复
一次传一组会使得状况好的网络大量占用着带宽及网络时间,而状况差的,就会被底层越加排挤。
这个当然不能说明是问题。从理论上来讲,针对发送来说确实有一定的方便性。不过接收不是太有利,明显可能导致串包(线程不同,线程的并行导致顺序错误)。不过楼主可以试一试。
fieldisme 2007-12-12
  • 打赏
  • 举报
回复
我是把数据分成N段用链表串上的,问题是传给WSARecv和WSASend缓冲区的时候,可以一次传一个WSABUF指针,也可以传一个WSABUF数组,一次传一个WSABUF是没问题的,但一次传一个数组岂不是更好,把N段缓冲赋给其buf,形如
WSABUF *WSAbuffer=new WSABUF[n];

for(int i=0;i<10;i++)
WSAbuffer[i].buf=X;//X是从链表上取下的缓冲区,每次循时X的值不同
WSASend(...WSAbuffer,10.....);

其中n是不固定长度的,只能动态创建,难道用完后又要释放,肯定不行,如果再创建一条链表来管理这个数组,其开销应该比其带来的好处还可观,我只是奇怪为什么设计这个函数时要传入的是数组而不是链表。

也许这个问题根本不存在,可能是我钻牛角尖了,每次只传一个缓冲区就可以了,等收到完成通知后缓冲区满后再换一个缓冲区。但我是希望其效率更高
僵哥 2007-12-12
  • 打赏
  • 举报
回复
内存池差不多就是类似的东西。

发送的时候,也可以把一段数据分成N段固定大小的数据块的不?用链表串上就好了。
fieldisme 2007-12-12
  • 打赏
  • 举报
回复
只要缓冲区大小是定值,则创建多大都没用意义,因为数据有可能很大,也可能是一条命令,即然是一个类,肯定得考虑其通用性呀

1,316

社区成员

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

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