为什么我的WSASend会立即返回,值为0,表示成功,且客户端能正常接收发送去的数据。

时间:2022-09-12 08:30:37
一般WSASend都会返回SOCK_ERROR,表示投递重叠成功,完成后从GetQueuedCompletionStatus处可以得到相应的信息,但我的返回了0,根本不会从GetQueuedCompletionStatus那儿获得任何完成信息,怎么回事呀?
我用的是AcceptEx,为了调试,我只投递了一个AcceptEx,然后我就在GetQueuedCompletionStatus处等待完成,当客户连接了并发送了数据,GetQueuedCompletionStatus就返回,该处返回后代码如下:
b = GetQueuedCompletionStatus(dlg->CompletionPort, &BytesTransferred,
    (LPDWORD)&PerHandleKey, (LPOVERLAPPED *) &PerIoData, INFINITE);

switch(PerIoData->IoOptType)
{
case IO_ACCEPT:
//将连接的套接字与完成端口关联
PerHandleKey = (LPPER_HANDLE_KEY) GlobalAlloc(GPTR, sizeof(PER_HANDLE_KEY));

PerHandleKey->sClient = PerIoData->sClient;

pack = *((NetPacket*)(PerIoData->DataBuf.buf)); //分析数据包
switch(pack.opt)
{
case 12:  
AfxMessageBox(pack.userData);
pack.opt = 20;
strcpy(pack.userData,"返回的数据!");
break;
}

PerIoData->IoOptType = IO_SEND;
PerIoData->DataBuf.buf = (char*)&(pack);
PerIoData->DataBuf.len = sizeof(pack);

result = WSASend(PerHandleKey->sClient, &(PerIoData->DataBuf), 1, &SendBytes, 0,&(PerIoData->Overlapped), NULL);
if (result == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING)
{
return ;
}
就是最后这儿返回了0,请大家多指教,谢谢!

7 个解决方案

#1


你的socket句柄要这样创建:
WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);

#2


原因应该不是你说的,你看了《windows网络编程2版》的p140吗?它举的例子都是用socket创建的。

#3


参考MSDN的WSASend():

For overlapped sockets (created using WSASocket with flag WSA_FLAG_OVERLAPPED) sending information uses overlapped I/O, unless both lpOverlapped and lpCompletionRoutine are NULL. In that case, the socket is treated as a nonoverlapped socket.

#4


谢谢楼上的热情,我解决了,还是用的socket
但还有一个问题:
服务使用的AcceptEx,那客户连接时怎样操作更好?
我现在使用的是connect,send,因为服务要收到至少一个字的缓冲才连接返回,但这样一来,服务回收刚才连接时收到的那条数据,也就是说,我不希望触发IO_ACCEPT后再次触发IO_RECV,不知道你有何高见?

#5


我觉得客户端connect+send,服务端acceptex接到连接,并收到数据,不会再触发IO_RECV;
要不你试试WSAConnect()

#6


我用WSAConnect试了,返回0,但服务的GetQueuedCompletionStatus一直阻塞没返回,也就是说它没收到数据。

#7


up

#1


你的socket句柄要这样创建:
WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);

#2


原因应该不是你说的,你看了《windows网络编程2版》的p140吗?它举的例子都是用socket创建的。

#3


参考MSDN的WSASend():

For overlapped sockets (created using WSASocket with flag WSA_FLAG_OVERLAPPED) sending information uses overlapped I/O, unless both lpOverlapped and lpCompletionRoutine are NULL. In that case, the socket is treated as a nonoverlapped socket.

#4


谢谢楼上的热情,我解决了,还是用的socket
但还有一个问题:
服务使用的AcceptEx,那客户连接时怎样操作更好?
我现在使用的是connect,send,因为服务要收到至少一个字的缓冲才连接返回,但这样一来,服务回收刚才连接时收到的那条数据,也就是说,我不希望触发IO_ACCEPT后再次触发IO_RECV,不知道你有何高见?

#5


我觉得客户端connect+send,服务端acceptex接到连接,并收到数据,不会再触发IO_RECV;
要不你试试WSAConnect()

#6


我用WSAConnect试了,返回0,但服务的GetQueuedCompletionStatus一直阻塞没返回,也就是说它没收到数据。

#7


up