IOCP中的WSARecv()失败,WSAGetLastError()返回值为6.

neicole 2012-08-27 11:14:42
IOCP句柄成功创建了,
Server与Client的Socket连通了,并且能够使用send()发送数据到客户端来正常通讯。
IOCP线程也创建成功了,能从调试那里看见八个线程。
只是,在刚刚接收到clientSocket后进行WSARecv()操作返回-1,使用WSAGetLastError()得到结果为6。

检查了一个晚上,看不出问题来,求各路人士帮忙看看,走过路过都帮顶顶~

将部分代码粘上:
// 这函数用于创建IOCP的ServerSocket.
void IocpServerSocket::startServer(DataManage * elem)
{
this -> IocpServerSocket::setDataManage(elem); // 按照最传统的流程来的啦~
this -> IocpServerSocket::createIocpHandle();
this -> IocpServerSocket::createWordThread();
this -> BaseSocket::createTcpSocket();
this -> ServerSocket::sbind();
this -> ServerSocket::slisten();
this -> IocpServerSocket::createAcceptClientThread();
return;
}


// 用于接收客户端Socket的线程
DWORD WINAPI IocpServerSocket::acceptClientThread(LPVOID IpParam)
{
IocpServerSocket * myIocp = (IocpServerSocket *) IpParam;
BaseSocket accClient;
while(true){
if(myIocp -> acceptClientSocket(accClient)){ // 接收客户端
myIocp -> connectClientIocp(accClient); // 客户端连接IOCP
myIocp -> createSocketRevRequest(accClient); // 创建从客户端的IOCP接收数据请求
if(NULL != myIocp->dataManage){
myIocp->dataManage->afterAcceSock(accClient);
}
}
}
return 0;
}

acceptClientSocket运行正常。。 就不粘上来啦~

int IocpServerSocket::connectClientIocp(const BaseSocket & elem)
{
// 创建用来和套接字关联的单句柄数据信息结构
BaseSocket * information = new BaseSocket(elem); // 再创指针是因为得将信息存放于(内存)堆中,删除操作将在数据获取函数中进行处理

// 将接受套接字和完成端口关联
HANDLE result = CreateIoCompletionPort((HANDLE)(information->getSocket()), completionPort, (DWORD)information, 0);
// ...
return 1;
}


下面这里不知道哪里错了,返回值是6

int IocpServerSocket::createSocketRevRequest(const BaseSocket & elem)
{
// 为投递I/O操作指定OVERLAPPED结构,在堆中创建好对象,准备在接收数据时再读取这对象的首地址
PerIoData * data = new PerIoData();
data -> operationType = PerIoData::readData;
data -> dataBuff.buf = data -> charBuf;
data -> dataBuff.len = PerIoData::defaultBufSize;
data -> dataByte = PerIoData::defaultBufSize;

DWORD Flags = 0; // 这数据很重要,在传参时不能删除,
int r = WSARecv(elem.getSocket(), &(data->dataBuff), 1, &data->dataByte, &Flags, &(data -> overlapped), NULL);
if(SOCKET_ERROR == r){
// #ifdef IO_STANDARD_STREAM_INFORMATION
std::cerr << "createSocketRevRequest Error:" << GetLastError() << std::endl;
system("pause");
// #endif
}
return r;
}


最后大家顺便看看这个有没错:
BaseSocket * outSocket = NULL; // 用以接收数据,起标志作用,无需初始化
PerIoData * outData = NULL;
int result = GetQueuedCompletionStatus(completionPort, &BytesTransferred, (PULONG_PTR)&outSocket, (LPOVERLAPPED*)&outData, WSA_INFINITE);

----------------------------------------------------

std::cerr << "createSocketRevRequest Error:" << GetLastError() << std::endl;
GetLastError为6,据 http://neicole.blog.51cto.com/5621716/974823 , 〖6〗-句柄无效.
不过IOCP不用句柄啊,重叠才用啊,然后就去找看看完成端口的句柄,发觉也正常啊,
completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0);
completionPort 非NULL.
然后。。。 不解,求解救~
...全文
423 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
lidanger 2013-04-19
  • 打赏
  • 举报
回复
我也遇到这个问题。。多谢各位。。
neicole 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
你的PerIoData里面应该有个WSAOVERLAPPED成员吧,WSAOVERLAPPED又有个hEvent成员。
标准作法是对这个WSAOVERLAPPED成员执行:
memset(..., 0, sizeof(WSAOVERLAPPED));
[/Quote]


万分感谢,万分感谢,yang79tao您又帮了我了呢~ 成功啦~ 结帖~
neicole 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
OVERLAPPED overlapped;
你这不是有了吗?在PerIoData的构造函数里面,memset它为0。

我说的WSAOVERLAPPED与OVERLAPPED是一样的,为了完整性,win socket 2加上了WSAOVERLAPPED(因为send增加了一个WSASend, recv增加了一个WSARecv,所以OVERLAPPED也增加一个WSAOVERLAPPED,最后这一对是完全一样的)。
[/Quote]

哦,谢谢啦~ 明白了,修改过事后试试继续做做测试~
youngwolf 2012-08-28
  • 打赏
  • 举报
回复
OVERLAPPED overlapped;
你这不是有了吗?在PerIoData的构造函数里面,memset它为0。

我说的WSAOVERLAPPED与OVERLAPPED是一样的,为了完整性,win socket 2加上了WSAOVERLAPPED(因为send增加了一个WSASend, recv增加了一个WSARecv,所以OVERLAPPED也增加一个WSAOVERLAPPED,最后这一对是完全一样的)。
neicole 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
你的PerIoData里面应该有个WSAOVERLAPPED成员吧,WSAOVERLAPPED又有个hEvent成员。
标准作法是对这个WSAOVERLAPPED成员执行:
memset(..., 0, sizeof(WSAOVERLAPPED));
[/Quote]

这是我的PerIoData
class PerIoData 
{
public:
enum optType{
readData, // 读数据
writeData, // 写数据
rAwData, // 读写数据
undoData // 禁止操作
};
enum defaultPara{
defaultBufSize = 1024
};

public:
OVERLAPPED overlapped;
WSABUF dataBuff;
DWORD dataByte;
char charBuf[defaultBufSize];
int operationType;
int sn; // 数据成员记录序列号

public:
PerIoData();
PerIoData(const PerIoData &);
PerIoData(const OVERLAPPED &, const WSABUF &, DWORD, char buf[defaultBufSize], int &);

void setCharBuf(const char buf[defaultBufSize], int); // 设置charBuf
char * getCharBuf(char buf[defaultBufSize], int); // 获取charBuf

// 类复制
void ownDeepCopy(const PerIoData&);
PerIoData & operator = (const PerIoData &);

~PerIoData();
};


标准做法需要加个 WSAOVERLAPPED???
neicole 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
引用 2 楼 的回复:
如果不用事件句柄的话,应该设置为NULL。

在new之后可以用memset把
PerIoData设置为0
[/Quote]

谢谢~
只是。。 还是有点不是很明白,将它memset为0是什么原因呢?
  不设的话就会导致GetLastError() 6 的问题出现是么?
youngwolf 2012-08-28
  • 打赏
  • 举报
回复
你的PerIoData里面应该有个WSAOVERLAPPED成员吧,WSAOVERLAPPED又有个hEvent成员。
标准作法是对这个WSAOVERLAPPED成员执行:
memset(..., 0, sizeof(WSAOVERLAPPED));
微型蚂蚁 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
如果不用事件句柄的话,应该设置为NULL。
[/Quote]
在new之后可以用memset把
PerIoData设置为0
neicole 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
你贴的代码,和你所解释的,这样也成功了,那样也成功了,都不是问题的关键,关键在PerIoData这个类有问题,它没有创建事件句柄。
[/Quote]

[Quote=引用 2 楼 的回复:]
如果不用事件句柄的话,应该设置为NULL。
[/Quote]

哈哈,太好啦,原来问题的关键在于PerIoData的句柄。

一直还以为WSARecv就是需要绑定PerIoData的呢~  

不过还是不是很明白,具体是哪里设为NULL呢?  是指WSARecv的最后一个参数么?好像原来就为NULL.

求指教~
youngwolf 2012-08-28
  • 打赏
  • 举报
回复
如果不用事件句柄的话,应该设置为NULL。
youngwolf 2012-08-28
  • 打赏
  • 举报
回复
你贴的代码,和你所解释的,这样也成功了,那样也成功了,都不是问题的关键,关键在PerIoData这个类有问题,它没有创建事件句柄。

18,356

社区成员

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

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