在线等哈...进来发言送分,使用本板块置顶的IOCP封装类,在客户端发送数据时出现,堆被破坏

当我遇上-你 2011-10-31 03:14:05
代码如下
在线程中使用出现可能堆被破坏....
不开线程使用有完全正常,问下大家是怎么回事啊?
//发送数据
extern "C"
WIN32API
int SendPacket(SOCKET hSock,char * sendBuf,int nLen)
{
DWORD offset=0,total=0;
DWORD Flags = 0,SendByts = 0;
LPPER_IO_OPERATION_DATA PerIoData = NULL;
IOCP_HEADER header;
DWORD dwRet = 0;
int nPreLen = 8192,nNowLen = 0;
int nFiledLen = sizeof(int);

if(sendBuf == NULL) return 0;

//获取原始发送缓冲区大小
getsockopt(hSock,SOL_SOCKET,SO_SNDBUF,(char*)&nPreLen,&nFiledLen);
//设置新的发送缓冲区大小为0
setsockopt(hSock,SOL_SOCKET,SO_SNDBUF,(char*)&nNowLen,sizeof(nNowLen));

//分配单句柄数据内存
PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
if(PerIoData == NULL)
{
TRACE("分配内存失败\n");
return -1;
}

//计算总包数
total=nLen / PACKET_SIZE;
if(nLen % PACKET_SIZE != 0)total++;

memset(&header,0,sizeof(header));
//设置包标识符
header.Identify = (UINT)InterlockedIncrement((LONG*)&g_cId);
//设置总包数
SET_PACKET_COUNT(header.Flag,total);
for(DWORD i=0; i<total; i++)
{
//设置包头属性,拷贝包头
header.Offset = offset;
(i==(total-1))?SET_PACKET_END(header.Flag):RESET_PACKET_END(header.Flag);
(i==(total-1))?SET_PACKET_LEN(header.Flag,nLen % PACKET_SIZE):SET_PACKET_LEN(header.Flag,PACKET_SIZE);
header.CheckSum = header.Flag + header.Offset + header.Identify;

memset(PerIoData->Buffer,0,DATA_BUFSIZE);
//拷贝头数据
memcpy(PerIoData->Buffer,&header,sizeof(IOCP_HEADER));
//拷贝发送数据
memcpy(PerIoData->Buffer + sizeof(IOCP_HEADER),sendBuf + offset,GET_PACKET_LEN(header.Flag));
//调整位移
offset = offset + GET_PACKET_LEN(header.Flag);

Flags = 0;
PerIoData->DataBuf.len = sizeof(IOCP_HEADER) + GET_PACKET_LEN(header.Flag);
PerIoData->DataBuf.buf = PerIoData->Buffer;

//发送数据
if(WSASend(hSock, &(PerIoData->DataBuf), 1, &SendByts, Flags, NULL, NULL) == SOCKET_ERROR)
{
//如果不是“设备忙”错误,则关闭SOCKET,并删除与之相关的结构
if (WSAGetLastError() != ERROR_IO_PENDING)
{
TRACE("WSASend failed with error [%ld]\n",WSAGetLastError());
break;
}
}
//统计发送字节数
dwRet = dwRet + SendByts;
}
GlobalFree(PerIoData);

//设置发送缓冲区设置成原始大小
setsockopt(hSock,SOL_SOCKET,SO_SNDBUF,(char*)&nPreLen,sizeof(nPreLen));

return dwRet;
}


...全文
178 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
logens 2011-11-01
  • 打赏
  • 举报
回复
不太明白,顶一下
当我遇上-你 2011-11-01
  • 打赏
  • 举报
回复
今天测试了低版本的,暂时没发现内存问题,在继续测试其他方面的
yynetsdk 2011-11-01
  • 打赏
  • 举报
回复
看我的签名
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 maoxing63570 的回复:]
引用 14 楼 wswwxk 的回复:
这个实例简单测试了下,问题比板块的实例问题更多

咋这犀利
[/Quote]
也不见 飞机党 在这个版块活动了,在的话,还可以交流下
maoxing63570 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wswwxk 的回复:]
这个实例简单测试了下,问题比板块的实例问题更多
[/Quote]

咋这犀利
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 maoxing63570 的回复:]
引用 11 楼 wswwxk 的回复:

引用 9 楼 maoxing63570 的回复:
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅

是的,这个库在数据量大的情况下,有严重的内存泄露

如果是客户端出现泄露的话,那么我可能想到的就是你没用那个ReleasePacket来释放,对于服务端来说,那么他有个自定义堆,另外还有一个用模板写的小型池,也不知……
[/Quote]
不使用线程池,也会出问题,测试数据在1MB/S 以下正常,但是在10M/S左右的时候,内存迅速耗尽,使用量直线上升,明天在测试下
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 maoxing63570 的回复:]
引用 11 楼 wswwxk 的回复:

引用 9 楼 maoxing63570 的回复:
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅

是的,这个库在数据量大的情况下,有严重的内存泄露

貌似我没遇到过,如果用MFC的话,可以看下gh0st用的那个
http://www.codeproject.com/KB/IP/winsockiocp.aspx……
[/Quote]
这个实例简单测试了下,问题比板块的实例问题更多
maoxing63570 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wswwxk 的回复:]

引用 9 楼 maoxing63570 的回复:
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅

是的,这个库在数据量大的情况下,有严重的内存泄露
[/Quote]
如果是客户端出现泄露的话,那么我可能想到的就是你没用那个ReleasePacket来释放,对于服务端来说,那么他有个自定义堆,另外还有一个用模板写的小型池,也不知道你用没用线程池,还有就是,你怎么检测出有泄露的
maoxing63570 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wswwxk 的回复:]

引用 9 楼 maoxing63570 的回复:
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅

是的,这个库在数据量大的情况下,有严重的内存泄露
[/Quote]
貌似我没遇到过,如果用MFC的话,可以看下gh0st用的那个
http://www.codeproject.com/KB/IP/winsockiocp.aspx?msg=79399
当然,如果你要用心跳检测的话,你也可以直接去下个gh0st,然后从代码里提
小妹见的少,就这些了
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 maoxing63570 的回复:]
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅
[/Quote]
是的,这个库在数据量大的情况下,有严重的内存泄露
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 maoxing63570 的回复:]
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅
[/Quote]
你有比较好的IOCP实例吗?能分享下吗?之前没搞过网络....28733690@163.com
maoxing63570 2011-10-31
  • 打赏
  • 举报
回复
如果没记错的话,这个代码来源于飞机党发的一个开源的代码里,author是沈毅
Eleven 2011-10-31
  • 打赏
  • 举报
回复
你需要确保你的重叠结构体在发送的过程中不会被破坏,即在send发送数据的时候,没有地哦啊用GlobalFree来做释放操作
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 tan625747 的回复:]
&(PerIoData->DataBuf)
明显这有问题

每循环一次,分配一次DataBuf
[/Quote]
这里只是引用地址,没分配空间,
//分配单句柄数据内存
PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
if(PerIoData == NULL)
{
TRACE("分配内存失败\n");
return -1;
}
//函数结束释放
GlobalFree(PerIoData);
v_table 2011-10-31
  • 打赏
  • 举报
回复
你的重叠结构对象就一个,怎么能投递多个异步IO呢!
tan625747 2011-10-31
  • 打赏
  • 举报
回复
&(PerIoData->DataBuf)
明显这有问题

每循环一次,分配一次DataBuf
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 oyljerry 的回复:]
估计线程同步等问题,数据是否有冲突访问
[/Quote]
只有一个线程,就只负责发送数据
oyljerry 2011-10-31
  • 打赏
  • 举报
回复
估计线程同步等问题,数据是否有冲突访问
凌乱哥 2011-10-31
  • 打赏
  • 举报
回复
标记,表示不太懂,顶一个
当我遇上-你 2011-10-31
  • 打赏
  • 举报
回复
也不是一开始就处问题,而是发送成功几次后就回出现这个问题,
WSASend(hSock, &(PerIoData->DataBuf), 1, &SendByts, Flags, NULL, NULL)
删除发送,代码没问题
最近有项目要做一个高性能网络服务器,决定下功夫搞定完成端口(IOCP),最终花了一个星期终于把它弄清楚了,并用C++写了一个版本,效率很不错。 但,从项目的总体需求来考虑,最终决定上.net平台,因此又花了一天一夜弄出了一个C#版,在这与大家分享。 一些心得体会: 1、在C#中,不用去面对完成端口的操作系统内核对象,Microsoft已经为我们提供了SocketAsyncEventArgs,它封装IOCP的使用。请参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socketasynceventargs.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1。 2、我的SocketAsyncEventArgsPool使用List对象来存储对客户端来通信的SocketAsyncEventArgs对象,它相当于直接使用内核对象IoContext。我这样设计比用栈来实现的好处理是,我可以在SocketAsyncEventArgsPool池中找到任何一个与服务器连接的客户,主动向它发信息。而用栈来实现的话,要主动给客户发信息,则还要设计一个结构来存储已连接上服务器的客户。 3、对每一个客户端不管还发送还是接收,我使用同一个SocketAsyncEventArgs对象,对每一个客户端来说,通信是同步进行的,也就是说服务器高度保证同一个客户连接上要么在投递发送请求,并等待;或者是在投递接收请求,等待中。本例只做echo服务器,还未考虑由服务器主动向客户发送信息。 4、SocketAsyncEventArgs的UserToken被直接设定为被接受的客户端Socket。 5、没有使用BufferManager ,因为我在初始化给每一个SocketAsyncEventArgsPool中的对象分配一个缓冲区,发送使用Arrary.Copy来进行字符拷贝,不去改变缓冲区的位置,只改变使用的长度,因此在下次投递接收请求恢复缓冲区长度就可以了!如果要主动给客户发信息的话,可以new一个SocketAsyncEventArgs对象,或者在初始化中建立几个来专门用于主动发送信息,因为这种需求一般是进行信息群发,建立一个对象可以用于很多次信息发送,总体来看,这种花销不大,还减去了字符拷贝和消耗。 6、测试结果:(在我的笔记本上行的,我的本本是T420 I7 8G内存) 100客户 100,000(十万次)不间断的发送接收数据(发送和接收之间没有Sleep,就一个一循环,不断的发送与接收) 耗3004.6325 秒完成 总共 10,000,000 一千万次访问 平均每分完成 199,691.6 次发送与接收 平均每秒完成 3,328.2 次发送与接收 整个运行过程中,内存消耗在开始两三分种后就保持稳定不再增涨。 看了一下对每个客户端的延迟最多不超过2秒。
完成端口通讯服务器(IOCP Socket Server)设计 (六)功能强大的IOCP Socket Servre模块例程源码 Copyright © 2009 代码客(卢益贵)版权所有 QQ:48092788 源码博客:http://blog.csdn.net/guestcode 一、声明 版权声明: 1、通讯模块代码版权归作者所有; 2、未经许可不得全部或部分用于任何项目开发; 3、未经许可不得部分修改后再利用源码。 免责声明: 1、 由于设计缺陷或其它Bug造成的后果,作者不承担责任; 2、未经许可的使用作者不提供任何技术支持服务。 权利和义务: 1、任何获得源码并发现Bug的个人或单位均有义务向作者反映; 2、作者保留追究侵权者法律责任的权利。 二、开发背景 部分代码由前项目分离而来,尚未有应用考验,但对于初学者学习和进阶有很大帮助。性能上尚未有定论,但应该不会令你失望。 三、功能说明 1、可以关闭Socket的Buffer; 2、可以关闭MTU(不等待MTU满才发送); 3、可以多IP或多端口监听; 4、可以重用socket(主动关闭除外); 5、可以0缓冲接收(Socket的Buffe = 0,避免过多的锁定内存页); 6、可以0缓冲连接(客户端仅连接,不一定立即发数据); 7、可以条件编译: a、是否使用内核Singly-linked lists; b、是否使用处理线程(工作线程和处理线程分开); c、是否使用内核锁来同步链表。 8、可以实现集群服务器模式的通讯(有客户端socket); 9、可以单独设置每个连接的Data项来实现连接和Usernfo的关联; 10、每个线程有OnBegin和OnEnd,用于设置线程独立的对象(数据库会话对象); 11、可以提供详细的运行情况,便于了解IOCP下的机制,以及进行调试分析; 12、可以发起巨量连接和数据(需要硬件配置来支持)。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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