accept 和 AcceptEx 的问题?

wjb_yd 2011-03-25 10:31:17
AcceptEx带来了两个问题,第一,在工作线程中需要加一个分支,处理完成的accept的逻辑。第二,AcceptEx会顺便接受一些数据。

但是我没有处理DOS攻击的需求,所以只想开一个线程,不停的accept新连接,然后做投递WSARecv操作。问题是,accept返回的套接字好像不支持I/O重叠操作,WSAGetLastError() 返回10045。

我的问题是,如果让accept返回的套接字,支持WSA_FLAG_OVERLAPPED???
...全文
547 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjb_yd 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 jwybobo2007 的回复:]
你的代码估计是在细节上有问题,和accept没关系.
listensocket是重叠属性那accept肯定也是可以继承的


你看下<windows网络编程>,把里面的示例代码拿出来编译调试,然后再进行下对比.
[/Quote]

DWORD dwFlags; 改成 DWORD dwFlags = 0; 就可以了,这个是个IN,OUT参数...
jwybobo2007 2011-03-25
  • 打赏
  • 举报
回复
SOCKET listensock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
监听套接字设置成OVERLAPPED,accept后的就继承了OVERLAPPED
jwybobo2007 2011-03-25
  • 打赏
  • 举报
回复
你的代码估计是在细节上有问题,和accept没关系.
listensocket是重叠属性那accept肯定也是可以继承的


你看下<windows网络编程>,把里面的示例代码拿出来编译调试,然后再进行下对比.
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 shenyi0106 的回复:]
不设置NULL试试?
[/Quote]
不设置NULL一样是10045.
hakufly 2011-03-25
  • 打赏
  • 举报
回复
MSDN中:The WSAAccept function extracts the first connection on the queue of pending connections on socket s, 。。。The newly created socket has the same properties as socket s including asynchronous events registered with WSAAsyncSelect or with WSAEventSelect.
而你的代码中sListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
所以我觉得accept返回的套接字已经有了WSA_FLAG_OVERLAPPED属性。
对你的问题不是很懂,不过我建议想想其他可能出现问题的地方。
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复
不设置NULL试试?
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 shenyi0106 的回复:]
你的MSDN是虾米版本?难道和我们的不一样?

For connection-oriented sockets, WSARecv can indicate the graceful termination of the virtual circuit in one of two ways that depend on whether the socket is byte stream or m……
[/Quote]

lpNumberOfBytesRecvd
A pointer to the number, in bytes, received by this call if the receive operation completes immediately. If the lpOverlapped parameter is non-NULL, this parameter is optional and can be set to NULL.
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复

你的MSDN是虾米版本?难道和我们的不一样?

For connection-oriented sockets, WSARecv can indicate the graceful termination of the virtual circuit in one of two ways that depend on whether the socket is byte stream or message oriented. For byte streams, zero bytes having been read (as indicated by a zero return value to indicate success, and lpNumberOfBytesRecvd value of zero) indicates graceful closure and that no more bytes will ever be read. For message-oriented sockets, where a zero byte message is often allowable, a failure with an error code of WSAEDISCON is used to indicate graceful closure. In any case a return error code of WSAECONNRESET indicates an abortive close has occurred.


If an overlapped operation completes immediately, WSARecv returns a value of zero and the lpNumberOfBytesRecvd parameter is updated with the number of bytes received and the flag bits indicated by the lpFlags parameter are also updated. If the overlapped operation is successfully initiated and will complete later, WSARecv returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesRecvd and lpFlags are not updated. When the overlapped operation completes, the amount of data transferred is indicated either through the cbTransferred parameter in the completion routine (if specified), or through the lpcbTransfer parameter in WSAGetOverlappedResult. Flag values are obtained by examining the lpdwFlags parameter of WSAGetOverlappedResult.



wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 visualeleven 的回复:]
The socket function causes a socket descriptor and any related resources to be allocated and bound to a specific transport-service provider. Winsock will utilize the first available service provider t……
[/Quote]

请问,socket默认就带重叠I/O属性的话,为什么WSARecv还是报错10045了呢?
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 shenyi0106 的回复:]
C/C++ code

DWORD Flags = 0;
DWORD dwRecvBytes = 0;


WSARecv(xx, xx, 1, &RecvBytes, &Flags,xx, NULL)
[/Quote]

dwRecvBytes 这个参数我传的NULL,我看MSDN里说如果Overlapped结构体不是空的话,这个参数可以传递NULL的
Eleven 2011-03-25
  • 打赏
  • 举报
回复
The socket function causes a socket descriptor and any related resources to be allocated and bound to a specific transport-service provider. Winsock will utilize the first available service provider that supports the requested combination of address family, socket type and protocol parameters. The socket that is created will have the overlapped attribute as a default.
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 shenyi0106 的回复:]
WSARecv(lpNewConn->sSocketToRecv, &(lpIOData->OperatorBuf), 1,
NULL, 0, &(lpIOData->COverlapped), NULL)

__in_out LPDWORD lpFlags跑哪去了?
[/Quote]

我已经把lpFlags加上去了...
不加这个参数是10014,加上这个参数是10045...
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复
 
DWORD Flags = 0;
DWORD dwRecvBytes = 0;


WSARecv(xx, xx, 1, &RecvBytes, &Flags,xx, NULL)
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复
WSARecv(lpNewConn->sSocketToRecv, &(lpIOData->OperatorBuf), 1,
NULL, 0, &(lpIOData->COverlapped), NULL)

__in_out LPDWORD lpFlags跑哪去了?
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 shenyi0106 的回复:]
引用 5 楼 miaolingshaohua 的回复:
C/C++ code

int WSARecv(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD……

这个是不对的,如果不写……
[/Quote]

谢谢,SOCKET NewSocket = WSAAccept(sListen, NULL, NULL, NULL, 0);
我把那个参数改回去了,并且用了WSAAccept,又变成10045了...

呃,初学这个IOCP,实在找不到答案,网上搜了半天也没搜到点有用的东西。
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 miaolingshaohua 的回复:]
C/C++ code

int WSARecv(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD……
[/Quote]
这个是不对的,如果不写那个参数,肯定会出现10014的,因为那是个必须的参数,看看MSDN
用WSAAccept来接受,accept是socket1中的函数,不支持异步WSA_FLAG_OVERLAPPED属性
WSA_FLAG_OVERLAPPED是socket2才提供的属性,必须要用socket2的函数才能有支持
wjb_yd 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 miaolingshaohua 的回复:]
C/C++ code

int WSARecv(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD……
[/Quote]

呃,谢谢,现在变成10014了...

我还是贴代码吧

HANDLE hCompletionPort;
WSADATA CWsaData;
SYSTEM_INFO CSystemInfo;
SOCKADDR_IN CLocalAddr;
SOCKET sListen;
unsigned int nLoop;

if (0 != WSAStartup(MAKEWORD(2,2), &CWsaData))
{
cout << "WSAStartup Failed" << endl;
return;
}

//创建一个IO完成端口
hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

//确定处理器的数量
GetSystemInfo(&CSystemInfo);

for (nLoop = 0; nLoop < CSystemInfo.dwNumberOfProcessors * 2; nLoop++)
{
//根据处理器的数量创建相应多的处理线程
HANDLE thread = CreateThread(NULL, 0, ServerThread, hCompletionPort, 0, NULL);
CloseHandle(thread);
}

//创建一个监听套接字(进行重叠操作)
sListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

CLocalAddr.sin_family = AF_INET;
CLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
CLocalAddr.sin_port = htons(9990);

if (0 != bind(sListen, (PSOCKADDR)&CLocalAddr, sizeof(CLocalAddr)))
{
cout << "bind addr failed: " << WSAGetLastError() << endl;
return;
}

if (0 != listen(sListen, SOMAXCONN))
{
cout << "listen failed: " << WSAGetLastError() << endl;
return;
}

while (1)
{
SOCKET NewSocket = accept(sListen, NULL, NULL);

if (INVALID_SOCKET == NewSocket)
{
printf("socket accept failed:%d\n", WSAGetLastError());
continue;
}

LPCONNECT_INFO lpNewConn = new CONNECT_INFO();
memset(lpNewConn->cRecvBuffer, sizeof(lpNewConn->cRecvBuffer), 0);
memset(lpNewConn->cSendBuffer, sizeof(lpNewConn->cSendBuffer), 0);
lpNewConn->sSocketToRecv = NewSocket;
lpNewConn->sSocketToSend = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
strcpy(lpNewConn->cRemoteServerIp, REMOTE_SERVER_IP);
lpNewConn->wRemoteServerPort = REMOTE_SERVER_PORT;

LPPER_IO_DATA lpIOData = new PER_IO_DATA();
lpIOData->nSocketType = CLIENT_SOCKET;
lpIOData->nOperatorType = RECV;
lpIOData->OperatorBuf.buf = (char*)lpNewConn->cRecvBuffer;
lpIOData->OperatorBuf.len = 1000;
memset(&(lpIOData->COverlapped), 0, sizeof(OVERLAPPED));

DWORD dwFlags;
if (WSARecv(lpNewConn->sSocketToRecv, &(lpIOData->OperatorBuf), 1,
NULL, 0, &(lpIOData->COverlapped), NULL) == SOCKET_ERROR)
if (WSAGetLastError() != WSA_IO_PENDING)
{
cout << "WSARecv Failed: " << WSAGetLastError() << endl;
closesocket(lpNewConn->sSocketToRecv);
closesocket(lpNewConn->sSocketToSend);

delete lpNewConn;
delete lpIOData;

assert(false);
}
}

closesocket(sListen);
WSACleanup();
smwhotjay 2011-03-25
  • 打赏
  • 举报
回复
SOCKET listensock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

或socket 默认创建的就是overlapped的..
哈利路亚1874 2011-03-25
  • 打赏
  • 举报
回复

int WSARecv(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD lpFlags,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
// 调用的时候第四个参数lpFlags初始值为0就不会有10045错误了
shenyi0106 2011-03-25
  • 打赏
  • 举报
回复
WSAAccept
加载更多回复(2)

18,356

社区成员

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

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