完成端口中如何设置接收超时??????????

zhoujianhei 2005-01-07 09:10:09
用来判断恶意连接
使用setsockopt(lpOv->s,SOL_SOCKET,SO_RCVTIMEO..... 无效
...全文
826 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
CompletionPort 2005-01-18
  • 打赏
  • 举报
回复
mark
beipiao 2005-01-15
  • 打赏
  • 举报
回复
估计不行吧,你把连接丢给完成端口去管理了,实际的数据发送和接受完全由完成端口控制。

唉,可能是微软设计接口的时候没考虑掉,人家一心想的是怎么样让你用起来比较简单:),或者我们太笨,没想到怎么用它.

我觉得elssann(臭屁虫和他的开心果) 的笨办法其实也不错。
leaber 2005-01-14
  • 打赏
  • 举报
回复
楼上的看清题目再回答
MuseIn 2005-01-14
  • 打赏
  • 举报
回复
设置connect的超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案。偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使那些想避免在套接字调用过程中被锁定的应用程序,采取一种有序的方式,同时对多个套接字进行管理"(《Windows网络编程技术》原话)。使用方法与解释请见《Windows网络编程技术》。
  在使用此函数前,需先将socket设置为非锁定模式,这样,在connect时,才会立马跳过,同时,通常也会产生一个WSAEWOULDBLOCK错误,这个错误没关系。再执行select则是真正的超时。

WSADATA wsd;
SOCKET cClient;
int ret;
struct sockaddr_in server;
hostent *host=NULL;

if(WSAStartup(MAKEWORD(2,0),&wsd)){return 0;}
cClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(cClient==INVALID_SOCKET){return 0;}
//set Recv and Send time out
int TimeOut=6000; //设置发送超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
TimeOut=6000;//设置接收超时6秒
if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
//设置非阻塞方式连接
unsigned long ul = 1;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
if(ret==SOCKET_ERROR)return 0;

//连接
server.sin_family = AF_INET;
server.sin_port = htons(25);
server.sin_addr .s_addr = inet_addr((LPCSTR)pSmtp);
if(server.sin_addr.s_addr == INADDR_NONE){return 0;}

connect(cClient,(const struct sockaddr *)&server,sizeof(server));

//select 模型,即设置超时
struct timeval timeout ;
fd_set r;

FD_ZERO(&r);
FD_SET(cClient, &r);
timeout.tv_sec = 15; //连接超时15秒
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);
if ( ret <= 0 )
{
::closesocket(cClient);
return 0;
}
//一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
unsigned long ul1= 0 ;
ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
if(ret==SOCKET_ERROR){
::closesocket (cClient);
return 0;
}
zhoujianhei 2005-01-14
  • 打赏
  • 举报
回复
up
leaber 2005-01-10
  • 打赏
  • 举报
回复
UP 一下
zhoujianhei 2005-01-07
  • 打赏
  • 举报
回复
yes yes
ppp9419 2005-01-07
  • 打赏
  • 举报
回复
大家都没明白楼主的意思

每次我们调用WSARecv后,都是在内核里被PENDING
楼主的意思就是想让某个WSARecv PENDING指定的时间,如果指定的时间还没收到数据,就让WSARecv从GetQueuecompletionStatus这里返回

目前我想不到办法可以这样做
lion1900 2005-01-07
  • 打赏
  • 举报
回复
我靠
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED* lpOverlapped,
DWORD dwMilliseconds
);
最后一个参数dwMilliseconds就是超时设置,指定它为超时时间
GetQueuedCompletionStatus返回失败时,
调用GetLastError()得到错误码为TIME_OUT
xuzheng318 2005-01-07
  • 打赏
  • 举报
回复
int timeout = 0;
setsockopt(socket,SQL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
kingzai 2005-01-07
  • 打赏
  • 举报
回复
UINT ScavengePulingSockets( LPVOID pParam )
{
CThreadPool * pObject = (CThreadPool*)pParam;
if (pObject == NULL)
return 0;

int i,timeout=1000;
DWORD st;
int seconds, len;

while ( 1 )
{
// scavenge sockets
for ( i=0; i<OVERLAPPEDIONUM; i++ )
{
/*
if (pObject->m_IODATA[i].acceptSocket==NULL)
continue;*/


if ( pObject->m_IODATA[i].opState == stAccepting )
{
// stAccepting means AcceptEx() called, but no completion yet

// determine if the socket is connected
seconds = 0;
len = sizeof seconds;
if ( 0 == getsockopt( pObject->m_IODATA[i].acceptSocket, SOL_SOCKET,
SO_CONNECT_TIME, (char *) &seconds, &len ) )
{
if ( seconds != -1 && seconds * 1000 > timeout * 2 )
{
// closesocket() here causes an immediate IOCP notification
// with an error indication; that will cause our worker thread
// to call DoClose(). The state of the listener socket will
// determine whether the socket will be reopened to accept
// another connection, or whether it is left for dead.
CancelIo((HANDLE)pObject->m_IODATA[i].acceptSocket);
closesocket( pObject->m_IODATA[i].acceptSocket );
}
}
}
else if ( pObject->m_IODATA[i].opState == stReading )
{
// stAccepting means AcceptEx() called, but no completion yet

// determine if the socket is connected
seconds = 0;
len = sizeof seconds;
if ( 0 == getsockopt( pObject->m_IODATA[i].acceptSocket, SOL_SOCKET,
SO_CONNECT_TIME, (char *) &seconds, &len ) )
{
if ( seconds != -1 && seconds * 1000 > timeout * 600)
{
// closesocket() here causes an immediate IOCP notification
// with an error indication; that will cause our worker thread
// to call DoClose(). The state of the listener socket will
// determine whether the socket will be reopened to accept
// another connection, or whether it is left for dead.
CancelIo((HANDLE)pObject->m_IODATA[i].acceptSocket);
closesocket( pObject->m_IODATA[i].acceptSocket );
}
}
}
else if ( pObject->m_IODATA[i].opState == stWriting )
{
// stAccepting means AcceptEx() called, but no completion yet

// determine if the socket is connected
seconds = 0;
len = sizeof seconds;
if ( 0 == getsockopt( pObject->m_IODATA[i].acceptSocket, SOL_SOCKET,
SO_CONNECT_TIME, (char *) &seconds, &len ) )
{
if ( seconds != -1 && seconds * 1000 > timeout * 600)
{
// closesocket() here causes an immediate IOCP notification
// with an error indication; that will cause our worker thread
// to call DoClose(). The state of the listener socket will
// determine whether the socket will be reopened to accept
// another connection, or whether it is left for dead.
CancelIo((HANDLE)pObject->m_IODATA[i].acceptSocket);
closesocket( pObject->m_IODATA[i].acceptSocket );
}
}
}
}

// pause until next run due
st = WaitForSingleObject( g_suicideEvent,100);
if ( st != WAIT_TIMEOUT )
break;
}
return 0;
}
zhoujianhei 2005-01-07
  • 打赏
  • 举报
回复
to alphapiao 谢谢
我用的是完成端口

to zhangqu_980371 谢谢
我要的是recv超时,非connect 超时
zhangqu_980371 2005-01-07
  • 打赏
  • 举报
回复
nResult = getsockopt(
lpCurentNode->sClient,
SOL_SOCKET,
SO_CONNECT_TIME,
(char*)&nOptval,
&nOptlen
);
if ((nOptval!=0xFFFFFFFF) && (nOptval>300)) // 超时为效连接。
{
// 处理它
}
alphapiao 2005-01-07
  • 打赏
  • 举报
回复
//deTime INFINITE为无限等待
VOID CMyUDP::SetTimeOut(DWORD deTime)
{
DWORD optval;
if(deTime)
{
optval=0;
ioctlsocket(m_sock,FIONBIO,(DWORD*)&optval);

if(INFINITE==deTime)
optval=0;
else
optval=deTime;

setsockopt(m_sock,SOL_SOCKET, SO_RCVTIMEO, (char *)&optval, sizeof(int));

}
else
{
optval=1;
ioctlsocket(m_sock,FIONBIO,(DWORD*)&optval);
}
}
elssann 2005-01-07
  • 打赏
  • 举报
回复
Members
Internal
Reserved for internal use. The Internal member is used internally by the entity that implements overlapped I/O. For service providers that create sockets as installable file system (IFS) handles, this parameter is used by the underlying operating system. Other service providers (non-IFS providers) are free to use this parameter as necessary.
InternalHigh
Reserved. Used internally by the entity that implements overlapped I/O. For service providers that create sockets as IFS handles, this parameter is used by the underlying operating system. NonIFS providers are free to use this parameter as necessary.
Offset
Reserved for use by service providers.
OffsetHigh
Reserved for use by service providers.
hEvent
If an overlapped I/O operation is issued without an I/O completion routine (lpCompletionRoutine is null), then this parameter should either contain a valid handle to a WSAEVENT object or be null. If lpCompletionRoutine is non-null then applications are free to use this parameter as necessary.


看这个吧,如果有方便的办法设置估计也就在这几个参数里了
leaber 2005-01-07
  • 打赏
  • 举报
回复
哪位还有更好的办法??

顶一下
zhoujianhei 2005-01-07
  • 打赏
  • 举报
回复
没有其他办法实现吗??
elssann 2005-01-07
  • 打赏
  • 举报
回复
HunterForPig(留着口水的猪) :

拜托,你这个是GetQueuedCompletionStatus的超时值。楼主要的是针对每个IO操作都能设定超时,完全不一样的东西。

楼主可以考虑自己为每个IO维护一个信息表,定时遍历信息表,发现某个IO超时还没完成,就调用CancelIo来取消。这个方法比较笨。

如果是防止对方第一次连接上来后就不发送数据,可以在对方刚连接上来的时候把他加入到一个链表,当发送了数据后就从链表中移除。 同时开一个线程定时遍历这个链表来获取连接时间,超过了时间还在链表里的连接就把关掉。

HunterForPig 2005-01-07
  • 打赏
  • 举报
回复
GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED* lpOverlapped,
DWORD dwMilliseconds
);
dwMilliseconds 这个不就可以设置
leaber 2005-01-07
  • 打赏
  • 举报
回复
是呀是呀

18,356

社区成员

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

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