找回密码
 加入
搜索
查看: 10907|回复: 14

[网络通信] TCPConnect超时问题解决了吗?TCPTimeout无用。IP不存在延迟20秒,正确0.02秒[已解决]

 火.. [复制链接]
发表于 2012-2-22 10:43:53 | 显示全部楼层 |阅读模式
本帖最后由 shuren88 于 2012-2-22 23:05 编辑

;TCPConnect超时问题解决了吗?TCPTimeout无用。IP不存在延迟20秒,正确则0.02秒。
TCPStartUp()
AutoItSetOption ("TCPTimeout", 200)        ;不起作用,IP不存在将延迟20秒。IP和端口正确则0.02秒。
$Socket = TCPConnect("10.1.0.110", 8899)
MsgBox(0, "" , "end")
If $socket <> 1 and $socket <>-1 and $socket <>2 Then
msgbox (32,"OK","端口是开放的!^_^")
Else
msgbox (16,"ERROR","发现错误了!^_^")
endif
TCPCloseSocket($Socket)
发表于 2012-2-22 20:26:20 | 显示全部楼层
本帖最后由 pusofalse 于 2012-2-22 20:28 编辑

连接前先将套接字模式设为非阻塞模式,调用连接函数时(au3中为TCPConnect,系统函数则是Ws2_32.dll中的connect)会立刻返回失败,而不会发生阻塞,连接正在后台进行,接着调用select函数,并指定一个超时时间,等待连接成功,如果等待超时,则关闭套接字句柄。

Const $tagTIMEVAL = "long Seconds;long Microseconds"
Const $tagFD_SET = "long NumberofSockets;handle Socket[64]"
Const $tagSOCKADDR = "word Family;word Port;long Address;ubyte Zero[8]"

Const $SOCKET_SUCCESS = 0
Const $SOCKET_ERROR = -1

TCPStartup()

$hSocket = _TCPConnectEx("10.1.0.110", 8899, 1000, 0)

If $hSocket < 1 Then
        MsgBox(48, "Error", "Timed out.")
Else
        MsgBox(48, "OK", "Connect successfully.")
EndIf

TCPCloseSocket($hSocket)

Func _WSAAccept($hSocket, $pSockAddr, $iSockAddr, $pCondition, $pContext = 0)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "handle", "WSAAccept", "handle", $hSocket, "ptr", $pSockAddr, "long*", $iSockAddr, "ptr", $pCondition, "ptr", $pContext)

        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_WSAAccept


Func _TCPConnectEx($sIPAddress, $iPort, $iMilliseconds = 5000, $fBlocking = 1)
        Local $hSocket = _socket(2, 1, 6)
        If $hSocket < 1 Then Return SetError(@error, 0, 0)

        If _ioctlsocket($hSocket, 0x8004667E, 1, "bool*") = $SOCKET_ERROR Then
                Return SetError(@error, _closesocket($hSocket), 0)
        EndIf

        Local $tSockAddr = DllStructCreate($tagSOCKADDR)
        Local $pSockAddr = DllStructGetPtr($tSockAddr)

        DllStructSetData($tSockAddr, "Family", 2)
        DllStructSetData($tSockAddr, "Port", _htons($iPort))
        DllStructSetData($tSockAddr, "Address", _inet_addr($sIPAddress))

        If _connect($hSocket, $pSockAddr, DllStructGetSize($tSockAddr)) = $SOCKET_SUCCESS Then
                If $fBlocking Then
                        _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")
                EndIf

                Return $hSocket
        Else
                Local $tWritefds = DllStructCreate($tagFD_SET)
                Local $pWritefds = DllStructGetPtr($tWritefds)

                DllStructSetData($tWritefds, "NumberofSockets", 1)
                DllStructSetData($tWritefds, "Socket", $hSocket, 1)

                If _select(0, $pWritefds, 0, $iMilliseconds) = 0 Then
                        Return SetError(10060, _closesocket($hSocket), 0)
                EndIf

                If $fBlocking Then
                        _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")
                EndIf

                Return $hSocket
        EndIf
EndFunc        ;==>_TCPConnectEx

Func _connect($hSocket, $pSockAddr, $iSockAddr)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "connect", "handle", $hSocket, "ptr", $pSockAddr, "long", $iSockAddr)

        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_connect

Func _htons($iHostWord)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "word", "htons", "word", $iHostWord)

        Return $iResult[0]
EndFunc        ;==>_htons

Func _inet_addr($sIPAddress)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "inet_addr", "str", $sIPAddress)

        Return $iResult[0]
EndFunc        ;==>_inet_addr

Func _closesocket($hSocket)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "closesocket", "handle", $hSocket)

        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_closesocket

Func _soerr()
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "WSAGetLastError")

        Return $iResult[0]
EndFunc        ;==>_soerr

Func _ioctlsocket($hSocket, $iCommand, $iValue, $sValueType = "long*")
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "ioctlsocket", "handle", $hSocket, "long", $iCommand, $sValueType, $iValue)

        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_ioctlsocket

Func _socket($iAfamily, $iType, $iProtocol)
        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "handle", "socket", "long", $iAfamily, "long", $iType, "long", $iProtocol)
        
        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_socket

Func _select($pReadfds, $pWritefds, $pExceptfds, $iMilliseconds = -1)
        Local $tTimeval = DllStructCreate($tagTIMEVAL)
        Local $pTimeval = DllStructGetPtr($tTimeval)

        DllStructSetData($tTimeval, "Seconds", 0)
        DllStructSetData($tTimeval, "Microseconds", $iMilliseconds * 1000)

        Local $iResult
        $iResult = DllCall("Ws2_32.dll", "long", "select", "long", 0, "ptr", $pReadfds, "ptr", $pWritefds, "ptr", $pExceptfds, "ptr", $pTimeval)

        Return SetError(_soerr(), 0, $iResult[0])
EndFunc        ;==>_select

评分

参与人数 2金钱 +110 贡献 +40 收起 理由
xms77 + 60 + 20 今天正好用到了,P大厉害啊!
lpxx + 50 + 20 厉害、佩服

查看全部评分

 楼主| 发表于 2012-2-22 21:54:44 | 显示全部楼层
谢谢大侠指点,下载来试一试
 楼主| 发表于 2012-2-22 23:04:30 | 显示全部楼层
非常感谢超级版主pusofalse不吝赐教,已经试验成功。
发表于 2013-3-26 18:05:39 | 显示全部楼层
经常CPU被阻塞到 80%以上,结果在这里得到解决,感恩超级版主pusofalse !!!!
发表于 2013-5-12 09:24:42 | 显示全部楼层
P大真是大好人一个。
发表于 2014-8-7 10:36:03 | 显示全部楼层
发表于 2014-8-10 11:24:48 | 显示全部楼层
这个虽然好用,但要注意使用环境,如在玩网络游戏时,不要平凡切换到无阻塞模式,即有可能导致 穿越火线 或者 逆战 掉线,提示设置无阻塞通宵失败。
发表于 2015-4-9 11:53:03 | 显示全部楼层
本帖最后由 kk_lee69 于 2015-4-9 12:04 编辑

回复 2# pusofalse

Func _TCPConnectEx($sIPAddress, $iPort, $iMilliseconds = 5000, $fBlocking = 1)
        Local $hSocket = _socket(2, 1, 6)
        If $hSocket < 1 Then Return SetError(@error, 0, 0)
 
        If _ioctlsocket($hSocket, 0x8004667E, 1, "bool*") = $SOCKET_ERROR Then
                Return SetError(@error, _closesocket($hSocket), 0)
        EndIf
 
        Local $tSockAddr = DllStructCreate($tagSOCKADDR)
        Local $pSockAddr = DllStructGetPtr($tSockAddr)
 
        DllStructSetData($tSockAddr, "Family", 2)
        DllStructSetData($tSockAddr, "Port", _htons($iPort))
        DllStructSetData($tSockAddr, "Address", _inet_addr($sIPAddress))
 
        If _connect($hSocket, $pSockAddr, DllStructGetSize($tSockAddr)) = $SOCKET_SUCCESS Then
                If $fBlocking Then
                        _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")
                EndIf
 
                Return $hSocket
        Else
                Local $tWritefds = DllStructCreate($tagFD_SET)
                Local $pWritefds = DllStructGetPtr($tWritefds)
 
                DllStructSetData($tWritefds, "NumberofSockets", 1)
                DllStructSetData($tWritefds, "Socket", $hSocket, 1)
 
                If _select(0, $pWritefds, 0, $iMilliseconds) = 0 Then
                        Return SetError(10060, _closesocket($hSocket), 0)
                EndIf
 
                If $fBlocking Then
                        _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")
                EndIf
 
                Return $hSocket
        EndIf
EndFunc ;==>_TCPConnectEx


請教一下  P大
問題一  第一行的  $fBlocking  參數 是指 如果我希望  這個函數跑完以後 希望設置為 阻塞模式的話 則設定為  $fBlocking=1  是嗎??
問題二  如果問題一的答案是  肯定的話   那麼 意思 就是說  這個函數  內定測試的時候 會以 無阻塞模式測試連線的結果 而測試完畢 內定會設回阻塞模式對嗎??
問題三  請問上面 哪一行 為 設定測試的時候 使用  無阻塞模式呢??
問題四  第18行  _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")  這個是指 將 模式 設定回 阻塞模式對嗎??
发表于 2015-4-10 10:31:19 | 显示全部楼层
回复 2# pusofalse

老大 在請教一下
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms738573(v=vs.85).aspx

The WSAAsyncSelect and WSAEventSelect functions automatically set a socket to nonblocking mode. If WSAAsyncSelect or WSAEventSelect has been issued on a socket, then any attempt to use ioctlsocket to set the socket back to blocking mode will fail with WSAEINVAL.

To set the socket back to blocking mode, an application must first disable WSAAsyncSelect by calling WSAAsyncSelect with the lEvent parameter equal to zero, or disable WSAEventSelect by calling WSAEventSelect with the lNetworkEvents parameter equal to zero.


该WSAAsyncSelect和WSAEventSelect功能自动设置一个套接字非阻塞模式。如果WSAAsyncSelect或WSAEventSelect已经发布了一个插座,那么任何试图使用ioctlsocket设置套接字回阻塞模式将失败,WSAEINVAL。

设置套接字回阻塞模式,应用程序必须先禁用WSAAsyncSelect调用WSAAsyncSelect与LEVENT参数等于零,或禁用WSAEventSelect通过调用WSAEventSelect与lNetworkEvents参数等于零。

意思是  如果我利用上面的 _TCPConnectEx  建立了一個非阻塞連接,那麼我無法在不關閉socket的情況下  利用 ioctlsocket function 在將他設回 阻塞模式嗎??
发表于 2015-4-10 23:53:06 | 显示全部楼层
回复 10# kk_lee69

可以设置回 阻塞模式 以后 不换插座 ,直接使用!
发表于 2016-4-27 17:01:23 | 显示全部楼层
回复 2# pusofalse


    问题一    $fBlocking  参数 是指 如果我希望  这个函数跑完以后 希望设置为 阻塞模式的话 则设定为  $fBlocking=1  是吗??
问题二  如果问题一的答案是  肯定的话   那么 意思 就是说  这个函数  内定测试的时候 会以 无阻塞模式测试联机的结果 而测试完毕 内定会设回阻塞模式对吗??
问题三  请问上面 哪一行 为 设定测试的时候 使用  无阻塞模式呢??
问题四    _ioctlsocket($hSocket, 0x8004667E, 0, "bool*")  这个是指 将 模式 设定回 阻塞模式对吗??
发表于 2016-4-30 20:59:24 | 显示全部楼层
回复 11# tvzml

我想請問的是  這個函數 0 是 阻塞模式  還是 1 是 阻塞模式
发表于 2017-1-16 16:31:52 | 显示全部楼层
发表于 2018-8-4 12:31:19 | 显示全部楼层
如果一直用非阻塞模式。该如何设置发送跟接收超时时间呢?
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-20 10:31 , Processed in 0.082768 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表