funkey Posted August 27, 2013 Posted August 27, 2013 (edited) Hello, if an IP address is not reachable then TCPConnect lasts about 21 seconds for me the return with the error. Now I wrote a function using my socket_UDF to set a timeout if the IP address cannot be reached. Have fun. _TCPConnectTimeout example expandcollapse popup#include "socket_UDF.au3" Global $iTimerStart, $iSock Global $TestIP = "1.2.3.4" Global $TestPort = 800 Global $ConnectionTimeout = 1000 _WSAStartup() Global $iTimerStart = TimerInit() $iSock = _TCPConnectTimeout($TestIP, $TestPort, $ConnectionTimeout) ConsoleWrite("_TCPConnectTimeout error: " & @error & " / new socket: " & $iSock & @CRLF) ConsoleWrite("Function lasts: " & Round(TimerDiff($iTimerStart), 3) & @LF) $iTimerStart = TimerInit() $iSock = TCPConnect($TestIP, $TestPort) ConsoleWrite("TCPConnect error: " & @error & " / new socket: " & $iSock & @CRLF) ConsoleWrite("Function lasts: " & Round(TimerDiff($iTimerStart), 3) & @LF) ; about 21 seconds for me _WSACleanup() Exit Func _TCPConnectTimeout($IP, $Port, $Timeout) Local Const $WSAEWOULDBLOCK = 10035 Local $iSocket, $iResult, $tTimeout, $tWrite, $tErr $iSocket = _socket() If $iSocket = $SOCKET_ERROR Then Return SetError(1, 0, -1) $iResult = _ioctlsocket($iSocket, $FIONBIO, 1) ; nonblocking socket If $iResult <> 0 Then _closesocket($iSocket) Return SetError(2, 0, -1) EndIf $iResult = _connect($iSocket, $IP, $Port) If $iResult = $SOCKET_ERROR Then If _WSAGetLastError() = $WSAEWOULDBLOCK Then $tWrite = DllStructCreate($tagFd_set) $tErr = DllStructCreate($tagFd_set) _FD_SET($iSocket, $tWrite) _FD_SET($iSocket, $tErr) $iResult = _selectEx(0, DllStructGetPtr($tWrite), DllStructGetPtr($tErr), $Timeout) If $iResult <= 0 Then _closesocket($iSocket) Return SetError(3, 0, -1) ;timeout Else If Not _FD_ISSET($iSocket, $tWrite) Then _closesocket($iSocket) Return SetError(4, 0, -1) ; $tErr must have been set EndIf EndIf Else _closesocket($iSocket) Return SetError(5, 0, -1) ; another WSA error EndIf EndIf $iResult = _ioctlsocket($iSocket, $FIONBIO, 0) ; blocking socket again If $iResult <> 0 Then _closesocket($iSocket) Return SetError(6, 0, -1) EndIf Return $iSocket EndFunc ;==>_TCPConnectTimeoutsocket_UDF expandcollapse popup#include-once ; Some socket functions ; Author: funkey ; Project start 2013.03.12 ; Actual project date 2013.08.27 Global Const $tagIN_ADDR = "ulong S_addr;" Global Const $tagSockAddr = "USHORT sa_family;char sa_data[14]" Global Const $tagSockAddr_In = "short sin_family;USHORT sin_port;ULONG sin_addr;char sin_zero[8]" Global Const $tagSockAddr_Storage = "short ss_family;char ss_pad1[6];INT64 ss_align;char ss_pad1[112]" Global Const $tagTimeVal = "long tv_sec;long tv_usec" Global Const $tagAddrInfo = "int ai_flags;int ai_family;int ai_socktype;int ai_protocol;uint ai_addrlen;ptr ai_canonname;ptr ai_addr;ptr ai_next" Global Const $FD_SETSIZE = 64 Global Const $tagFd_set = "UINT fd_count;UINT fd_array[" & $FD_SETSIZE & "]" Global Const $AF_UNSPEC = 0 Global Const $AF_UNIX = 1 Global Const $AF_INET = 2 Global Const $AF_IMPLINK = 3 Global Const $AF_PUP = 4 Global Const $AF_CHAOS = 5 Global Const $AF_IPX = 6 Global Const $AF_NS = 6 Global Const $AF_ISO = 7 Global Const $AF_OSI = $AF_ISO Global Const $AF_ECMA = 8 Global Const $AF_DATAKIT = 9 Global Const $AF_CCITT = 10 Global Const $AF_SNA = 11 Global Const $AF_DECnet = 12 Global Const $AF_DLI = 13 Global Const $AF_LAT = 14 Global Const $AF_HYLINK = 15 Global Const $AF_APPLETALK = 16 Global Const $AF_NETBIOS = 17 Global Const $AF_VOICEVIEW = 18 Global Const $AF_FIREFOX = 19 Global Const $AF_UNKNOWN1 = 20 Global Const $AF_BAN = 21 Global Const $AF_ATM = 22 Global Const $AF_INET6 = 23 Global Const $SOCKET_ERROR = -1 Global Const $INVALID_SOCKET = -1 Global Const $SOCK_STREAM = 1 Global Const $SOCK_DGRAM = 2 Global Const $SOCK_RAW = 3 Global Const $SOCK_RDM = 4 Global Const $SOCK_SEQPACKET = 5 Global Const $IPPROTO_IP = 0 Global Const $IPPROTO_ICMP = 1 Global Const $IPPROTO_IGMP = 2 Global Const $IPPROTO_GGP = 3 Global Const $IPPROTO_TCP = 6 Global Const $IPPROTO_PUP = 12 Global Const $IPPROTO_UDP = 17 Global Const $IPPROTO_IDP = 22 Global Const $IPPROTO_ND = 77 Global Const $IPPROTO_RAW = 255 Global Const $SOL_SOCKET = 0xFFFF ;SOL_SOCKET Socket Options ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms740532(v=vs.85).aspx Global Const $IP_OPTIONS = 1 Global Const $SO_DEBUG = 1 Global Const $SO_ACCEPTCONN = 2 Global Const $SO_REUSEADDR = 4 ; BOOLEAN Global Const $SO_KEEPALIVE = 8 Global Const $SO_DONTROUTE = 16 Global Const $SO_BROADCAST = 32 ;INT Global Const $SO_USELOOPBACK = 64 Global Const $SO_LINGER = 128 Global Const $SO_OOBINLINE = 256 Global Const $SO_EXCLUSIVEADDRUSE = -5 ; BOOLEAN (~SO_REUSEADDR) Global Const $SO_DONTLINGER = -129 ; (~SO_LINGER) Global Const $SO_SNDBUF = 0x1001 Global Const $SO_RCVBUF = 0x1002 Global Const $SO_SNDLOWAT = 0x1003 Global Const $SO_RCVLOWAT = 0x1004 Global Const $SO_SNDTIMEO = 0x1005 ; DWORD Global Const $SO_RCVTIMEO = 0x1006 ; DWORD Global Const $SO_ERROR = 0x1007 Global Const $SO_TYPE = 0x1008 Global Const $FIONBIO = 0x8004667E Global Const $FIONREAD = 0x4004667F Global Const $FIOASYNC = 0x8004667D Global Const $SIOCSHIWAT = 0x80047300 Global Const $SIOCGHIWAT = 0x80047301 Global Const $SIOCSLOWAT = 0x80047302 Global Const $SIOCGLOWAT = 0x80047303 Global Const $SIOCATMARK = 0x40047307 ;max backlog for listen() Global Const $SOMAXCONN = 0x7fffffff ;flags for send(to) Global Const $MSG_DONTROUTE = 4 Global Const $MSG_OOB = 1 Global $hDLL_WS2_32 = 0 Func _WSAStartup() If $hDLL_WS2_32 = 0 Then $hDLL_WS2_32 = DllOpen("ws2_32.dll") If $hDLL_WS2_32 = -1 Then $hDLL_WS2_32 = 0 Return 0 EndIf If TCPStartup() = 0 Then ;TCPStartup() is equal to WSAStartup function DllClose($hDLL_WS2_32) $hDLL_WS2_32 = 0 Return 0 EndIf EndIf Return 1 EndFunc ;==>_WSAStartup Func _WSACleanup() If $hDLL_WS2_32 <> 0 Then TCPShutdown() ;TCPShutdown() is equal to WSACleanup function DllClose($hDLL_WS2_32) $hDLL_WS2_32 = 0 EndIf Return 1 EndFunc ;==>_WSACleanup Func _setsockopt($iSocket, $iLevel, $iOptName, $tOptVal) Local $iOptLen = DllStructGetSize($tOptVal) Local $aRet = DllCall($hDLL_WS2_32, "int", "setsockopt", "uint", $iSocket, "int", $iLevel, "int", $iOptName, "struct*", $tOptVal, "int", $iOptLen) Return $aRet[0] EndFunc ;==>_setsockopt Func _getsockopt($iSocket, $iLevel, $iOptName, ByRef $tOptVal) Local $iOptLen = DllStructGetSize($tOptVal) Local $aRet = DllCall($hDLL_WS2_32, "int", "setsockopt", "uint", $iSocket, "int", $iLevel, "int", $iOptName, "struct*", $tOptVal, "int", $iOptLen) Return $aRet[0] EndFunc ;==>_getsockopt Func _socket($AF = $AF_INET, $SocketType = $SOCK_STREAM, $Protocol = $IPPROTO_TCP) ; AF_INET, SOCK_STREAM, IPPROTO_TCP Local $aRet = DllCall($hDLL_WS2_32, "int", "socket", "int", $AF, "int", $SocketType, "int", $Protocol) Return $aRet[0] EndFunc ;==>_socket Func _closesocket($iSocket) Local $aRet = DllCall($hDLL_WS2_32, "int", "closesocket", "UINT", $iSocket) Return $aRet[0] EndFunc ;==>_closesocket ;shutdown() allows you to cut off communication in a certain direction, or both ways (just like closesocket() does.) ;0 Further receives are disallowed ;1 Further sends are disallowed ;2 Further sends and receives are disallowed (like closesocket()) ;It's important to note that shutdown() doesn't actually close the file descriptor — it just changes ;its usability. To free a socket descriptor, you need to use closesocket(). Func _shutdown($iSocket, $iHow) Local $aRet = DllCall($hDLL_WS2_32, "int", "shutdown", "UINT", $iSocket, "int", $iHow) Return $aRet[0] EndFunc ;==>_shutdown Func _bind($iSocket, $sIP, $iPort) Local $tSockAddr_In = DllStructCreate($tagSockAddr_In) Local $pSockAddr_In = DllStructGetPtr($tSockAddr_In) Local $iSizeSockAddr_In = DllStructGetSize($tSockAddr_In) DllStructSetData($tSockAddr_In, "sin_family", $AF_INET) DllStructSetData($tSockAddr_In, "sin_port", _htons($iPort)) DllStructSetData($tSockAddr_In, "sin_addr", _inet_addr($sIP)) Local $aRet = DllCall($hDLL_WS2_32, "int", "bind", "UINT", $iSocket, "struct*", $pSockAddr_In, "int", $iSizeSockAddr_In) Return $aRet[0] EndFunc ;==>_bind Func _connect($iSocket, $sIP, $iPort) Local $tSockAddr_In = DllStructCreate($tagSockAddr_In) Local $iSizeSockAddr_In = DllStructGetSize($tSockAddr_In) DllStructSetData($tSockAddr_In, "sin_family", $AF_INET) DllStructSetData($tSockAddr_In, "sin_port", _htons($iPort)) DllStructSetData($tSockAddr_In, "sin_addr", _inet_addr($sIP)) Local $aRet = DllCall($hDLL_WS2_32, "int", "connect", "UINT", $iSocket, "struct*", $tSockAddr_In, "int", $iSizeSockAddr_In) Return $aRet[0] EndFunc ;==>_connect Func _listen($iSocket, $iBacklog = $SOMAXCONN) Local $aRet = DllCall($hDLL_WS2_32, "int", "listen", "UINT", $iSocket, "int", $iBacklog) Return $aRet[0] EndFunc ;==>_listen Func _accept($iSocket, ByRef $sIP, ByRef $iPort) Local $tAddr = DllStructCreate($tagSockAddr_In) Local $aRet = DllCall($hDLL_WS2_32, "UINT", "accept", "UINT", $iSocket, "struct*", $tAddr, "int*", DllStructGetSize($tAddr)) $iPort = _ntohs(DllStructGetData($tAddr, 2)) $sIP = _inet_ntoa(DllStructGetData($tAddr, 3)) Return $aRet[0] EndFunc ;==>_accept Func _select(ByRef $tReadFds, $iTimeout) Local $tTimeout = DllStructCreate($tagTimeVal) DllStructSetData($tTimeout, "tv_sec", Floor($iTimeout / 1000)) DllStructSetData($tTimeout, "tv_usec", ($iTimeout - DllStructGetData($tTimeout, "tv_sec") * 1000) * 1000) Local $aRet = DllCall($hDLL_WS2_32, "int", "select", "int", 0, "struct*", $tReadFds, "ptr", 0, "ptr", 0, "struct*", $tTimeout) Return $aRet[0] ;-1 = error; 0 = timeout; else data! EndFunc ;==>_select Func _selectEx($pReadFds, $pWriteFds, $pExceptFds, $iTimeout) Local $tTimeout = DllStructCreate($tagTimeVal) DllStructSetData($tTimeout, "tv_sec", Floor($iTimeout / 1000)) DllStructSetData($tTimeout, "tv_usec", ($iTimeout - DllStructGetData($tTimeout, "tv_sec") * 1000) * 1000) Local $aRet = DllCall($hDLL_WS2_32, "int", "select", "int", 0, "ptr", $pReadFds, "ptr", $pWriteFds, "ptr", $pExceptFds, "struct*", $tTimeout) Return $aRet[0] ;-1 = error; 0 = timeout; else data! EndFunc ;==>_selectEx Func _FD_ZERO(ByRef $tFd_set) DllStructSetData($tFd_set, "fd_count", 0) EndFunc ;==>_FD_ZERO Func _FD_SET($iSock, ByRef $tFd_set) Local $iCount = DllStructGetData($tFd_set, "fd_count") For $i = 0 To $iCount - 1 If DllStructGetData($tFd_set, "fd_Array", $i + 1) = $iSock Then ExitLoop EndIf Next If $i = $iCount Then If $iCount < $FD_SETSIZE Then DllStructSetData($tFd_set, "fd_array", $iSock, $i + 1) DllStructSetData($tFd_set, "fd_count", $iCount + 1) EndIf EndIf EndFunc ;==>_FD_SET Func _FD_CLR($iSock, ByRef $tFd_set) Local $iCount = DllStructGetData($tFd_set, "fd_count") For $i = 0 To $iCount - 1 If DllStructGetData($tFd_set, "fd_array", $i + 1) = $iSock Then While ($i < $iCount - 1) DllStructSetData($tFd_set, "fd_array", DllStructGetData($tFd_set, "fd_array", $i + 2), $i + 1) $i += 1 WEnd EndIf DllStructSetData($tFd_set, "fd_count", $iCount - 1) ExitLoop Next EndFunc ;==>_FD_CLR Func _FD_ISSET($iSock, ByRef $tFd_set) Local $aRet = DllCall($hDLL_WS2_32, "int", "__WSAFDIsSet", "UINT", $iSock, "struct*", $tFd_set) Return $aRet[0] EndFunc ;==>_FD_ISSET Func _send($iSocket, ByRef $tBuffer, $iFlags = 0) Local $iLen = DllStructGetSize($tBuffer) Local $aRet = DllCall($hDLL_WS2_32, "int", "send", "int", $iSocket, "struct*", $tBuffer, "int", $iLen, "int", $iFlags) Return $aRet[0] EndFunc ;==>_send Func _sendto($iSocket, ByRef $tBuffer, ByRef $tTo, $iFlags = 0) Local $iLen = DllStructGetSize($tBuffer) Local $iLenTo = DllStructGetSize($tTo) Local $aRet = DllCall($hDLL_WS2_32, "int", "sendto", "int", $iSocket, "struct*", $tBuffer, "int", $iLen, "int", $iFlags, "struct*", $tTo, "int", $iLenTo) Return $aRet[0] EndFunc ;==>_sendto Func _recv($iSocket, ByRef $tBuffer, $iFlags = 0) Local $iLen = DllStructGetSize($tBuffer) Local $aRet = DllCall($hDLL_WS2_32, "int", "recv", "uint", $iSocket, "struct*", $tBuffer, "int", $iLen, "int", $iFlags) Return $aRet[0] EndFunc ;==>_recv Func _recvfrom($iSocket, ByRef $tBuffer, ByRef $tFrom, $iFlags = 0) Local $iLen = DllStructGetSize($tBuffer) Local $iLenFrom = DllStructGetSize($tFrom) Local $aRet = DllCall($hDLL_WS2_32, "int", "recvfrom", "uint", $iSocket, "struct*", $tBuffer, "int", $iLen, "int", $iFlags, "struct*", $tFrom, "int", $iLenFrom) Return $aRet[0] EndFunc ;==>_recvfrom Func _inet_addr($sIP) Local $aRet = DllCall($hDLL_WS2_32, "ULONG", "inet_addr", "str", $sIP) Return $aRet[0] EndFunc ;==>_inet_addr Func _inet_ntoa($pIn_Addr) ;only IPv4 (deprecated) --> use _inet_ntop() instead Local $aRet = DllCall($hDLL_WS2_32, "str", "inet_ntoa", "ptr", $pIn_Addr) Return $aRet[0] EndFunc ;==>_inet_ntoa Func _inet_ntop($pIn_Addr, $iFamily = $AF_INET) ;IPv4 and IPv6 --> Vista and above Local $tBuffer = DllStructCreate("char[46]") ;16 for IPv4, 46 for IPv6 Local $aRet = DllCall($hDLL_WS2_32, "str", "inet_ntop", "int", $iFamily, "ptr", $pIn_Addr, "struct*", $tBuffer, "int", DllStructGetSize($tBuffer)) Return DllStructGetData($tBuffer, 1) EndFunc ;==>_inet_ntop ;host byte order to network byte order (double) Func _htond($value) Local $aRet = DllCall($hDLL_WS2_32, "UINT64", "htond", "double", $value) Return $aRet[0] EndFunc ;==>_htond ;host byte order to network byte order (float) Func _htonf($value) Local $aRet = DllCall($hDLL_WS2_32, "UINT", "htonf", "float", $value) Return $aRet[0] EndFunc ;==>_htonf ;host byte order to network byte order (long) Func _htonl($value) Local $aRet = DllCall($hDLL_WS2_32, "ULONG", "htonl", "ULONG", $value) Return $aRet[0] EndFunc ;==>_htonl ;host byte order to network byte order (long long) Func _htonll($value) Local $aRet = DllCall($hDLL_WS2_32, "UINT64", "htonll", "UINT64", $value) Return $aRet[0] EndFunc ;==>_htonll ;host byte order to network byte order (short) Func _htons($iPort) Local $aRet = DllCall($hDLL_WS2_32, "USHORT", "htons", "USHORT", $iPort) Return $aRet[0] EndFunc ;==>_htons ;network byte order to host byte order (double) Func _ntohd($value) Local $aRet = DllCall($hDLL_WS2_32, "double", "ntohd", "UINT64", $value) Return $aRet[0] EndFunc ;==>_ntohd ;network byte order to host byte order (float) Func _ntohf($value) Local $aRet = DllCall($hDLL_WS2_32, "float", "ntohf", "UINT", $value) Return $aRet[0] EndFunc ;==>_ntohf ;network byte order to host byte order (long) Func _ntohl($iNetLong) Local $aRet = DllCall($hDLL_WS2_32, "ULONG", "ntohl", "ULONG", $iNetLong) Return $aRet[0] EndFunc ;==>_ntohl ;network byte order to host byte order (long long) Func _ntohll($value) Local $aRet = DllCall($hDLL_WS2_32, "UINT64", "ntohll", "UINT64", $value) Return $aRet[0] EndFunc ;==>_ntohll ;network byte order to host byte order (short) Func _ntohs($iNetShort) Local $aRet = DllCall($hDLL_WS2_32, "USHORT", "ntohs", "USHORT", $iNetShort) Return $aRet[0] EndFunc ;==>_ntohs Func _WSAGetLastError() Local $aRet = DllCall($hDLL_WS2_32, "int", "WSAGetLastError") Return $aRet[0] EndFunc ;==>_WSAGetLastError Func _GetLocalPort($iSocket) ;funkey Local $tagIN_ADDR = "ulong S_addr;" Local $tagSockAddr_In = "short sin_family;ushort sin_port;ptr sin_addr;char sin_zero[8];" Local $tIn_Addr = DllStructCreate($tagIN_ADDR) Local $tName = DllStructCreate($tagSockAddr_In) DllStructSetData($tName, "sin_addr", DllStructGetPtr($tIn_Addr)) Local $aRes = DllCall($hDLL_WS2_32, "int", "getsockname", "uint", $iSocket, "struct*", $tName, "int*", 512) Local $aRes2 = DllCall($hDLL_WS2_32, "ushort", "ntohs", "ushort", DllStructGetData($tName, 2)) Return $aRes2[0] EndFunc ;==>_GetLocalPort Func _getsockname($iSocket) Local $tIn_Addr = DllStructCreate($tagIN_ADDR) Local $tName = DllStructCreate($tagSockAddr_In) DllStructSetData($tName, "sin_addr", DllStructGetPtr($tIn_Addr)) Local $aRes[2] Local $aRet = DllCall($hDLL_WS2_32, "int", "getsockname", "uint", $iSocket, "struct*", $tName, "int*", 512) If Not @error And $aRet[0] = 0 Then $aRes[0] = _inet_ntoa(DllStructGetData($tName, "sin_addr")) ;IP address $aRes[1] = _ntohs(DllStructGetData($tName, "sin_port")) ;IP port ;~ $aRes[2] = DllStructGetData($tName, "sin_family") ; always AF_INET !? Return $aRes EndIf Return SetError(1, 0, 0) EndFunc ;==>_getsockname ;More than TCPNameToIP(), returns an array of IP addresses Func _getaddrinfo($sNodeName) Local $pResult, $tAddrInfo, $sIP Local $aRet = DllCall($hDLL_WS2_32, "int", "getaddrinfo", "str", $sNodeName, "ptr", 0, "ptr", 0, "ptr*", 0) $pResult = $aRet[4] Do $tAddrInfo = DllStructCreate($tagAddrInfo, $pResult) Local $tName = DllStructCreate($tagSockAddr_In, DllStructGetData($tAddrInfo, "ai_addr")) $sIP &= _inet_ntoa(DllStructGetData($tName, "sin_addr")) & ";" $pResult = DllStructGetData($tAddrInfo, "ai_next") Until $pResult = 0 _freeaddrinfo($aRet[4]) Return StringSplit(StringTrimRight($sIP, 1), ";", 2) EndFunc ;==>_getaddrinfo Func _freeaddrinfo($pAddrInfo) DllCall($hDLL_WS2_32, "none", "freeaddrinfo", "ptr", $pAddrInfo) EndFunc ;==>_freeaddrinfo Func _ioctlsocket($iSocket, $iCmd, $iArg) Local $aRet = DllCall($hDLL_WS2_32, "int", "ioctlsocket", "uint", $iSocket, "long", $iCmd, "ULONG*", $iArg) Return $aRet[0] EndFunc ;==>_ioctlsocket Func _TCPConnectEx($sIP, $iRemPort, $iRcvTimeOut = 0, $iSendTimeOut = 0, $iLocPort = -1) Local $tTimeVal, $iSockError, $iBind, $iConnect, $aIP[1] Local $iSock = _socket($AF_INET, $SOCK_STREAM, $IPPROTO_TCP) If $iRcvTimeOut > 0 Then $tTimeVal = DllStructCreate("DWORD timeout") DllStructSetData($tTimeVal, "timeout", $iRcvTimeOut) $iSockError = _setsockopt($iSock, $SOL_SOCKET, $SO_RCVTIMEO, $tTimeVal) If $iSockError Then _closesocket($iSock) Return SetError(1, _WSAGetLastError(), 0) EndIf EndIf If $iSendTimeOut > 0 Then $tTimeVal = DllStructCreate("DWORD timeout") DllStructSetData($tTimeVal, "timeout", $iSendTimeOut) $iSockError = _setsockopt($iSock, $SOL_SOCKET, $SO_SNDTIMEO, $tTimeVal) If $iSockError Then _closesocket($iSock) Return SetError(2, _WSAGetLastError(), 0) EndIf EndIf If $iLocPort >= 0 Then $iBind = _bind($iSock, @IPAddress1, $iLocPort) If $iBind Then _closesocket($iSock) Return SetError(3, _WSAGetLastError(), 0) EndIf EndIf If _IsValidIP($sIP) Then $aIP[0] = $sIP Else $aIP = _getaddrinfo($sIP) EndIf $iConnect = _connect($iSock, $aIP[0], $iRemPort) If $iConnect Then _closesocket($iSock) Return SetError(4, _WSAGetLastError(), 0) EndIf Return $iSock EndFunc ;==>_TCPConnectEx Func _IsValidIP($sIP) Local $aIP = StringSplit($sIP, ".") If $aIP[0] <> 4 Then Return SetError(1, 0, 0) For $x = 1 To $aIP[0] If $aIP[$x] < 0 Or $aIP[$x] > 255 Then Return SetError(2, 0, 0) Next Return 1 EndFunc ;==>_IsValidIP TCPConnectTimeout & socket UDF.rar Edited August 27, 2013 by funkey EKY32 1 Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning.
argumentum Posted January 16, 2017 Posted January 16, 2017 (edited) On 8/27/2013 at 11:56 AM, funkey said: _getsockopt Hi @funkey, I was looking for the optimum TCP MaxLen for TCPRecv , getsockopt() would be it. But there is no example of use in the provided files nor a simple "getsockopt()" call that would return the size, On top of all that, I may have no idea of what or how to ask. Also, now that I looked at https://www.autoitscript.com/forum/topic/181645-winsock-udf/ from @j0kky, your code may be wrong in that function, as is the same as setsockopt() . Any answer from anyone is welcomed, as I'd like to know why the default 1024 when MTU is usually 1500, but .... all these are way over my head. Still wanna know if there is a way to ask the OS for a optimum value. Edit: maybe RegRead("HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters","TcpWindowSize") gives the value ?, if so, would it work on the internet as well as LAN ? Edited January 16, 2017 by argumentum Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
RTFC Posted January 17, 2017 Posted January 17, 2017 (edited) @argumentum: Have a look at _Pool_SetTCPsocketOptions in my Pool environment, and the associated constants. Be careful not to confuse the size of the MTU with the size of the TCP buffer, which can hold multiple MTUs. I use: Quote Global Const $_POOL_MTU_TCP      =576      ; for our purposes; on Ethernet 1,472 bytes Global Const $_POOL_MTU_TCPBUFFER=0x4470   ; Ethernet; theoretical max: 0xffff; see also HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ <interface-name> AFAIK, 1472 bytes is the max packet size on LAN. To be honest, my fading brain has trouble recalling where I derived the (multiple-MTU) buffer size of 0x4470h, but the way to figure it out for your system would be to repeatedly call setsockopt followed by getsockopt (to evaluate whether the call was successful) with ever larger buffer sizes, until it fails. EDIT: See also here and here. And see my _Pool_Client_Received for an example of how to deal with packet fragmentation. Hope this helps. Edited January 17, 2017 by RTFC argumentum 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable  CodeCrypter  CodeScanner  DigitalDisplay  Eigen4AutoIt  FAT Suite   HighMem  MetaCodeFileLibrary  OSgrid  Pool  RdRand  SecondDesktop  SimulatedAnnealing  Xbase I/O
funkey Posted January 17, 2017 Author Posted January 17, 2017 Maybe I never used this function? I don't even know! Here an example:  expandcollapse popupGlobal Const $SO_SNDBUF = 0x1001 Global Const $SO_RCVBUF = 0x1002 Global Const $SOL_SOCKET = 0xFFFF Global Const $SO_MAX_MSG_SIZE = 0x2003 Global $Domain = "www.google.com" TCPStartup() Global $IP = TCPNameToIP($Domain) Global $iSock = TCPConnect($IP, 80) If $iSock = -1 Then ConsoleWrite("Connection error!" & @CRLF) Exit EndIf Global $tResult = DllStructCreate("int") Global $iRes = _getsockopt($iSock, $SOL_SOCKET, $SO_SNDBUF, $tResult) If $iRes = 0 Then ConsoleWrite("send buffer size = " & DllStructGetData($tResult, 1) & @CRLF) EndIf Global $iRes = _getsockopt($iSock, $SOL_SOCKET, $SO_RCVBUF, $tResult) If $iRes = 0 Then ConsoleWrite("receive buffer size = " & DllStructGetData($tResult, 1) & @CRLF) EndIf TCPCloseSocket($iSock) Func _getsockopt($iSocket, $iLevel, $iOptName, ByRef $tOptVal) Local $iOptLen = DllStructGetSize($tOptVal) Local $aRet = DllCall("WS2_32.DLL", "int", "getsockopt", "int", $iSocket, "int", $iLevel, "int", $iOptName, "struct*", $tOptVal, "int*", $iOptLen) Return $aRet[0] EndFunc ;==>_getsockopt  argumentum 1 Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning.
argumentum Posted January 18, 2017 Posted January 18, 2017 @funkey, thanks a million, this exactly what I wanted.@RTFC, in https://en.wikipedia.org/wiki/Maximum_transmission_unit , they give a nice explanation ( nice becouse is dumbed down for me  ), where I gather that I should use the value of _getsockopt(), that in my case is 8192 ( in 2 XPs and 1 Win7 ) and deduct 22 bytes of protocol overhead and use that, 8170,  for MaxLen. Also in the example for TCPRecv in the AutoIt manual, a 4k size is used in the 2nd example ( send file ) , but I'd use the 8170 chunks ( _getsockopt() - 22 ). That should ensure maximum transmission speed. Although, thinking about it, I might as well say " I'll take 64k" ( as maxLen ), because the idea is to send in a way that is not fragmented, whatever came in, came in. Do correct me if my brainstorming is flawed Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
RTFC Posted January 18, 2017 Posted January 18, 2017 @argumentum: Hmmm, a few off-the-cuff remarks... 2 hours ago, argumentum said: I should use the value of _getsockopt(), This will return whatever it was most recently successfully set to by any other software, and does not necessarily reflect full capacity on your system. 2 hours ago, argumentum said: I might as well say " I'll take 64k" ( as maxLen ) I don't think that'll work. If you call getsockopt with a value that's too high, the call will simply fail (in my experience). That's why you should call getsockopt afterwards to check whether setsockopt succeeded. Plus, from a machine-code perspective, setting any capacity to (2^n) -1 is asking for trouble (read: buffer overflow/inadvertent wrap/page fault/etc...).  2 hours ago, argumentum said: the idea is to send in a way that is not fragmented, whatever came in, came in. Great idea, but reality tends to be messier. Will you be able to ensure that your Recv capacity will always exceed the Send load on your chosen port? How about if the hardware layer(s) underneath the TCP layer start running out of buffer space (e.g., due to a memory leak) or may themselves collect multiple packets before a flush (which then may exceed the capacity of your own buffer)? I would suggest you at least consider in your message handling that your socket buffer may at some point be filled completely before you get a chance to deal with it, with more data on the way/waiting in the wings. It may also be beneficial to make the buffer an exact multiple of your (fixed) packet size, so you won't have to rebuild packets from split fragments. All I'm saying is, you do not have full control over the hardware layers, so your software layer(s) should have contingency planning built in. That being said, 8K minus overhead sounds like a reasonable size to play with. But I would use a bit more overhead (maybe subtract 10% from maxlen, with a minimum of 128 bytes, or maybe one full packet size). Note also that if you were to use VPN to access your LAN (for example), VPN itself will add another header to your packet. It's stuff like that you discover only once you start chasing "impossible bugs." On top of that, these tend to be Heisenbugs, i.e., highly timing- and capacity-sensitive, and thus very difficult to hunt down and kill. Best not to invite those to your party... argumentum 1 My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable  CodeCrypter  CodeScanner  DigitalDisplay  Eigen4AutoIt  FAT Suite   HighMem  MetaCodeFileLibrary  OSgrid  Pool  RdRand  SecondDesktop  SimulatedAnnealing  Xbase I/O
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now