caleb41610 Posted October 22, 2012 Share Posted October 22, 2012 (edited) This is the base for most of my programs that require TCP. I've completely rewritten it with optimizations and proper packet handling, which can be added to easily.* Completely rewrote the script 11/04/12* Greatly optimized speed. 1000 connections in 4.02 seconds on my machine.* Added a vastly configurable packet system.* GUI changed slightly. (Still a minimalist example GUI)* Raw message packet example added* PNG image transfer packet example added* Username / Computername listview information packet example added.* WM_NOTIFY menu removedTBA features:* Packet checksum error checking* More examples* Client-to-client communication through the server* Better GUIGDIPlus and Crypt start up but are not used. I have plans to use them eventually so they were left in the script. Remove them if you want.I plan to add a check for pending connections and process them immediately instead of only processing one connection then continuing the main loop. Then you could theoretically have a lot more speed than you would with the current method of processing new connections.Multi-connection server:expandcollapse popup#region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_Res_Comment=Multi Client Server #AutoIt3Wrapper_Res_Fileversion=1.0.0.2 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y #AutoIt3Wrapper_Res_requestedExecutionLevel=requireAdministrator #AutoIt3Wrapper_Run_Tidy=y #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GUIConstantsEx.au3> #include <Array.au3> #include <WindowsConstants.au3> #include <GuiMenu.au3> #include <Crypt.au3> #include <GDIPlus.au3> #include <Base64.au3> TCPStartup() ; Starts up TCP _Crypt_Startup() ; Starts up Crypt _GDIPlus_Startup() ; Starts up GDIPlus #region ;**** Declares you can edit **** Opt("TrayIconDebug", 1) Global $BindIP = "0.0.0.0" ; IP Address to listen on. 0.0.0.0 = all available. Global $BindPort = "1337" ; Port to listen on. Global $MaxConnections = 1000 ; Maximum number of allowed connections. Global $PacketSize = 1000 ; Maximum size to receive when packets are checked. #endregion ;**** Declares you can edit **** #region ;**** Declares that shouldn't be edited **** OnAutoItExitRegister("_ServerClose") Opt("TCPTimeout", 0) Opt("GUIOnEventMode", 1) Global $WS2_32 = DllOpen("Ws2_32.dll") ; Opens Ws2_32.dll to be used later. Global $NTDLL = DllOpen("ntdll.dll") ; Opens NTDll.dll to be used later. Global $TotalConnections = 0 ; Holds total connection number. Global $SocketListen = -1 ; Variable for TCPListen() Global $Connection[$MaxConnections + 1][11] ; Array to connection information. Global $SocketListen Global $PacketEND = "[PACKET_END]" ; Defines the end of a packet Global $PacketMSG = "[PACKET_TYPE_0001]" ; Plain text message Global $PacketPNG = "[PACKET_TYPE_0002]" ; Base64 of PNG binary. Global $PacketPCI = "[PACKET_TYPE_0003]" ; UserName@PC name #endregion ;**** Declares that shouldn't be edited **** #region ;**** GUI **** Global $GUI = GUICreate("Server List", 300, 400) Global $ServerList = GUICtrlCreateListView("#|Socket|IP|User|Computer", 5, 5, 290, 360) Global $ServerMenu = GUICtrlCreateMenu("Server") Global $ServerStartListen = GUICtrlCreateMenuItem("On", $ServerMenu, 2, 1) Global $ServerStopListen = GUICtrlCreateMenuItem("Off", $ServerMenu, 3, 1) Global $ConnectionMenu = GUICtrlCreateMenu("Connection") Global $ConnectionKill = GUICtrlCreateMenuItem("Close", $ConnectionMenu, 1) GUICtrlCreateMenuItem("", $ConnectionMenu, 2) Global $ConnectionKillAll = GUICtrlCreateMenuItem("Close All", $ConnectionMenu, 3) GUISetOnEvent($GUI_EVENT_CLOSE, "_ServerClose") GUICtrlSetOnEvent($ServerStartListen, "_ServerListenStart") GUICtrlSetOnEvent($ServerStopListen, "_ServerListenStop") GUICtrlSetOnEvent($ConnectionKill, "_ConnectionKill") GUICtrlSetOnEvent($ConnectionKillAll, "_ConnectionKillAll") GUISetState(@SW_SHOW, $GUI) #endregion ;**** GUI **** _Main() ; Starts the main function Func _Main() While 1 _CheckNewConnections() _CheckNewPackets() _Sleep(1000, $NTDLL) WEnd EndFunc ;==>_Main Func _CheckNewConnections() Local $SocketAccept = TCPAccept($SocketListen) ; Tries to accept a new connection. If $SocketAccept = -1 Then ; If we found no new connections, Return ; skip the rest and return to _Main(). EndIf If $TotalConnections >= $MaxConnections Then ; If we reached the maximum connections allowed, TCPSend($SocketAccept, "MAXIMUM_CONNECTIONS_REACHED") ; tell the connecting client that we cannot accept the connection, TCPCloseSocket($SocketAccept) ; close the socket, Return ; skip the rest and return to _Main(). EndIf ; Since we got this far, we must have a new connection. $TotalConnections += 1 ; Add to the total connections. $Connection[$TotalConnections][0] = $SocketAccept ; Save the socket number to the next empty array slot, at sub array 0. $Connection[$TotalConnections][1] = GUICtrlCreateListViewItem($TotalConnections & "|" & $SocketAccept & "|" & _SocketToIP($SocketAccept), $ServerList) ; Create list view item with connection information EndFunc ;==>_CheckNewConnections Func _CheckBadConnection() If $TotalConnections < 1 Then Return ; If we have no connections, there is no reason to check for bad ones, so return to _Main() Local $NewTotalConnections = 0 ; Temporary variable to calculate the new total connections. For $i = 1 To $TotalConnections ; Loop through all TCPSend($Connection[$i][0], "CONNECTION_TEST") ; Send a test packet If @error Then ; If the send fails.. TCPCloseSocket($Connection[$i][0]) ; Close the socket, GUICtrlDelete($Connection[$i][1]) ; Delete the item from the list view, $Connection[$i][0] = -"" ; Set socket to nothing, $Connection[$i][1] = "" ; Empty gui control, ContinueLoop ; and continue checking for more bad connections. Else $NewTotalConnections += 1 ; If the send succeeded, we count up, because the client is still connected. EndIf Next If $NewTotalConnections < $TotalConnections Then ; If we found any bad connections, then we rearrange the $Connection array. If $NewTotalConnections < 1 Then ; If the new total shows no connections, $TotalConnections = $NewTotalConnections ; Set the new connection variable, Return ; and Return to _Main() EndIf ; This loop creates a temporary array, cycles through possible old data in the $Connection array and transfers it to the temporary array, rearranged properly. Local $Count = 1 Local $TempArray[$MaxConnections + 1][11] For $i = 1 To $MaxConnections If $Connection[$i][0] = -1 Or $Connection[$i][0] = "" Then ContinueLoop EndIf For $j = 0 To 10 $TempArray[$Count][$j] = $Connection[$i][$j] Next $Count += 1 Next $TotalConnections = $NewTotalConnections ; Self explanitory. $Connection = $TempArray ; Transfer the newly arranged temporary array to our main array. ; This loop doesn't directly affect anything with the connection, but makes the list numbered (or re-numbered, after the array was fixed.) For $i = 1 To $TotalConnections GUICtrlSetData($Connection[$i][1], $i) Next EndIf EndFunc ;==>_CheckBadConnection Func _CheckNewPackets() If $TotalConnections < 1 Then Return ; If we have no connections, there is no reason to check for bad ones, so return to _Main() EndIf Local $RecvPacket For $i = 1 To $TotalConnections ; Loop through all connections $RecvPacket = TCPRecv($Connection[$i][0], $PacketSize) ; Attempt to receive data If @error Then ; If there was an error, the connection is probably down. _CheckBadConnection() ; So, we call the function to check. EndIf If $RecvPacket <> "" Then ; If we got data... $Connection[$i][2] &= $RecvPacket ; Add it to the packet buffer. ConsoleWrite(">> New Packet from " & _SocketToIP($Connection[$i][0]) & @CRLF & "+> " & $RecvPacket & @CRLF & @CRLF) ; Let us know we got a packet in scite. EndIf If StringInStr($Connection[$i][2], $PacketEND) Then ; If we received the end of a packet, then we will process it. Local $RawPackets = $Connection[$i][2] ; Transfer all the data we have to a new variable. Local $FirstPacketLength = StringInStr($RawPackets, $PacketEND) - 30 ; Get the length of the packet, and subtract the length of the prefix/suffix. Local $PacketType = StringLeft($RawPackets, 18) ; Copy the first 18 characters, since that is where the packet type is put. Local $CompletePacket = StringMid($RawPackets, 19, $FirstPacketLength + 11) ; Extract the packet. Local $PacketsLeftover = StringTrimLeft($RawPackets, $FirstPacketLength + 41) ; Trim what we are using, so we only have what is left over. (any incomplete packets) $Connection[$i][2] = $PacketsLeftover ; Transfer any leftover packets back to the buffer. ; Writes some stuff to the console for debugging. ConsoleWrite(">> Full packet found!" & @CRLF) ConsoleWrite("+> Type: " & $PacketType & @CRLF) ConsoleWrite("+> Packet: " & $CompletePacket & @CRLF) ConsoleWrite("!> Left in buffer: " & $Connection[$i][2] & @CRLF & @CRLF) ; Since we extracted a packet, we will send it to the processor. _ProcessFullPacket($CompletePacket, $PacketType, $i) EndIf Next EndFunc ;==>_CheckNewPackets ; I think the processor is generally easy to understand. It was made to process any packet that is received in a very organized way, making new additions painless. ; Adding new packet types is easy. Define it at the top, and add a new Case statement in this function. Packet types are defined as "[PACKET_TYPE_0000]" ; Length of the packet type MUST be the same. If it's not, it will not be processed. Thus you should only change the number, 0000-9999. ; We process the packet based on the type. ; $PacketMSG Messages pop up in a message box. ; $PacketPNG PNG gets saved/ran. ; $PacketPCI PC info updates the list view with username and computer name. Func _ProcessFullPacket($CompletePacket, $PacketType, $ArraySlotNumber) Switch $PacketType Case $PacketMSG TrayTip("New message from " & _SocketToIP($Connection[$ArraySlotNumber][0]), $CompletePacket, 5, 1) ;MsgBox(0, "New Message", "Message From " & _SocketToIP($Connection[$ArraySlotNumber][0]) & @CRLF & @CRLF & $CompletePacket) Case $PacketPNG If StringLen($CompletePacket) > 1 Then ; This check must be added because _Base64Decode() will crash the script if it gets empty input. Local $Base64DecodedToPNGBinary = _Base64Decode($CompletePacket) Local $DateTime = "[" & @MON & "-" & @MDAY & "-" & @YEAR & "] [" & @HOUR & "-" & @MIN & "-" & @SEC & "]" Local $File = @ScriptDir & "" & $DateTime & ".png" Local $FileOpen = FileOpen($File, 2) FileWrite($FileOpen, $Base64DecodedToPNGBinary) FileClose($FileOpen) ShellExecute($File) Else MsgBox(16, "Error", "Received empty PNG packet.") EndIf Case $PacketPCI Local $PacketPCISplit = StringSplit($CompletePacket, "@", 1) Local $UserName = $PacketPCISplit[1] Local $CompName = $PacketPCISplit[2] GUICtrlSetData($Connection[$ArraySlotNumber][1], "|||" & $UserName & "|" & $CompName) EndSwitch EndFunc ;==>_ProcessFullPacket Func _ServerListenStart() ; Starts listening. If $SocketListen <> -1 Then MsgBox(16, "Error", "Socket already open.") Return Else $SocketListen = TCPListen($BindIP, $BindPort, $MaxConnections) ; Starts listening. If $SocketListen = -1 Then MsgBox(16, "Error", "Unable to open socket.") EndIf EndIf EndFunc ;==>_ServerListenStart Func _ServerListenStop() ; Stops listening. If $SocketListen = -1 Then MsgBox(16, "Error", "Socket already closed.") Return EndIf TCPCloseSocket($SocketListen) $SocketListen = -1 EndFunc ;==>_ServerListenStop Func _ServerClose() ; Exits properly. If $TotalConnections >= 1 Then For $i = 1 To $TotalConnections TCPSend($Connection[$i][0], "SERVER_SHUTDOWN") TCPCloseSocket($Connection[$i][0]) Next EndIf TCPShutdown() _GDIPlus_Shutdown() _Crypt_Shutdown() DllClose($NTDLL) DllClose($WS2_32) GUIDelete($GUI) Exit EndFunc ;==>_ServerClose Func _SocketToIP($SHOCKET) ; IP of the connecting client. Local $sockaddr = DllStructCreate("short;ushort;uint;char[8]") Local $aRet = DllCall($WS2_32, "int", "getpeername", "int", $SHOCKET, "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr)) If Not @error And $aRet[0] = 0 Then $aRet = DllCall($WS2_32, "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3)) If Not @error Then $aRet = $aRet[0] Else $aRet = 0 EndIf $sockaddr = 0 Return $aRet EndFunc ;==>_SocketToIP Func _Sleep($MicroSeconds, $NTDLL = "ntdll.dll") ; Faster sleep than Sleep(). Local $DllStruct $DllStruct = DllStructCreate("int64 time;") DllStructSetData($DllStruct, "time", -1 * ($MicroSeconds * 10)) DllCall($NTDLL, "dword", "ZwDelayExecution", "int", 0, "ptr", DllStructGetPtr($DllStruct)) EndFunc ;==>_Sleep Func _ConnectionKill() Local $selected = GUICtrlRead(GUICtrlRead($ServerList)) If Not $selected <> "" Then MsgBox(16, "Error", "Please select a connection first.") Return EndIf Local $StringSplit = StringSplit($selected, "|", 1) TCPCloseSocket($Connection[$StringSplit[1]][0]) EndFunc ;==>_ConnectionKill Func _ConnectionKillAll() If $TotalConnections >= 1 Then For $i = 1 To $MaxConnections If $Connection[$i][0] > 0 Then TCPSend($Connection[$i][0], "SERVER_SHUTDOWN") TCPCloseSocket($Connection[$i][0]) EndIf Next EndIf EndFunc ;==>_ConnectionKillAllExample script:expandcollapse popup#include <GUIConstantsEx.au3> #include <EditConstants.au3> #include <GuiEdit.au3> #include <WindowsConstants.au3> #include <Base64.au3> Global $PacketEND = "[PACKET_END]" ; Defines the end of a packet Global $PacketMSG = "[PACKET_TYPE_0001]" ; Plain text message Global $PacketPNG = "[PACKET_TYPE_0002]" ; Base64 of PNG binary. Global $PacketPCI = "[PACKET_TYPE_0003]" ; UserName@PC name $ip = @IPAddress1 $port = 1337 TCPStartup() $socket = TCPConnect($ip, $port) If @error Then MsgBox(16, "Error", "Could not connect. Exiting.") Exit EndIf Tests() Func Tests() ; Sends a plain message. MsgBox(0, "Test 1", "Sending a plain text message, the packet being sent is: " & @CRLF & @CRLF & $PacketMSG & "This is a test message." & $PacketEND) TCPSend($socket, $PacketMSG & "This is a test message." & $PacketEND) ; Sends the current user's name and the computers name. MsgBox(0, "Test 2", "Sending Username and Computername, the packet being sent is: " & @CRLF & @CRLF & $PacketPCI & @UserName & "@" & @ComputerName & $PacketEND) TCPSend($socket, $PacketPCI & @UserName & "@" & @ComputerName & $PacketEND) ; Sends Base64 converted Globe.png MsgBox(0, "Test 3", "Sending Globe.png, the packet being sent is too large to show, but would be: " & @CRLF & @CRLF & $PacketPNG & "Base64_converted_binary" & $PacketEND) $File = @ScriptDir & "" & "Globe.png" $FileOpen = FileOpen($File, 0) $FileRead = FileRead($FileOpen) $FileRead = BinaryMid($FileRead, 1, BinaryLen($FileRead)) $Encoded = _Base64Encode($FileRead) FileClose($FileOpen) $Base64PNG = $PacketPNG & $Encoded & $PacketEND $Length = StringLen($Base64PNG) For $i = 1 To $Length Step 1000 Sleep(10) TCPSend($socket, StringMid($Base64PNG, $i, 1000)) Next EndFuncTest connection speed:TCPStartup() Global Const $number_of_connections = 1000 ; Total number of connections to perform Global Const $ip = @IPAddress1 ; IP address Global Const $port = 1337 ; Port Global $connection_array[$number_of_connections + 1] Global $errors = 0 Global $test _Test() Func _Test() Local $count Local $timer = TimerInit() For $i = 1 To $number_of_connections $connection_array[$i] = TCPConnect($ip, $port) If @error Then $errors += 1 EndIf Next MsgBox(0, "", $number_of_connections & " connections in " & TimerDiff($timer) / 1000 & " seconds, with " & $errors & " error(s).") For $i = 1 To $number_of_connections TCPCloseSocket($connection_array[$i]) If @error Then $errors += 1 EndIf Next EndFunc TCPShutdown()Indentation still not working with copy/paste so here are the scripts:Server:Server.au3Examples:Example.au3Test Server Speed.au3Includes:Base64.au3The image you need for Example.au3:Save it as Globe.png Edited November 5, 2012 by caleb41610 Multi-Connection TCP Server Link to comment Share on other sites More sharing options...
caleb41610 Posted November 5, 2012 Author Share Posted November 5, 2012 * Completely rewrote the script 11/04/12* Greatly optimized speed. 1000 connections in 4.02 seconds on my machine.* Added a vastly configurable packet system.* GUI changed slightly. (Still a minimalist example GUI)* Raw message packet example added* PNG image transfer packet example added* Username / Computername listview information packet example added.* WM_NOTIFY menu removedLet me know what you think!Most of the script is commented but I may be more thorough with the next update.I have not added error checking to the packet system I made. I am thinking about adding some type of checksum/hash section to the packets and dump packets that are invalid and notify the connecting client that the server did not receive what they sent. I'm working a lot lately, but I found some time to update this. I hope it helps someone! Multi-Connection TCP Server Link to comment Share on other sites More sharing options...
ajit Posted November 6, 2012 Share Posted November 6, 2012 @caleb41610, Thanks for the script, just downloaded, works nice, got to play with it. Regards Ajit Link to comment Share on other sites More sharing options...
incepator Posted November 7, 2012 Share Posted November 7, 2012 (edited) Your method presented is interesting to me. The problem is that I have an IP like this: "192.168.1.64 Because of Ip can not make a connection with IP to IP ... .. than the local ... Real ip is "188.26.221.143" How to i make a real server ip and server to connect through other clients? Edited November 7, 2012 by incepator Link to comment Share on other sites More sharing options...
caleb41610 Posted November 7, 2012 Author Share Posted November 7, 2012 Your method presented is interesting to me.The problem is that I have an IP like this: "192.168.1.64Because of Ip can not make a connection with IP to IP ... ..than the local ...Real ip is "188.26.221.143"How to i make a real server ip and server to connect through other clients?BogQ explains it very well here, in post #6: Multi-Connection TCP Server Link to comment Share on other sites More sharing options...
incepator Posted November 7, 2012 Share Posted November 7, 2012 Thanks Link to comment Share on other sites More sharing options...
caleb41610 Posted December 2, 2012 Author Share Posted December 2, 2012 (edited) Deleted post Probably won't continue this program. I hope the sources helps someone. Edited December 24, 2012 by caleb41610 Multi-Connection TCP Server Link to comment Share on other sites More sharing options...
l4tran Posted December 4, 2012 Share Posted December 4, 2012 (edited) I found that the return message for tcpsend() and tcprecv() is not reliable, so I improved on it. The purpose of this is to send large amount of data with error checking in between. Basically, the data that is being sent is converted from a string to binary and then compressed. The compressed binary is then split into an array, each element being 1000 character in length. Each element is then sent to the receiver and expect the receiver to reply with a confirmation before continue sending the rest. On the receiving end, each element is compiled back into an array, and then from the array back into binary and finally decompressed back to string. This works well with files smaller than 5 megs. expandcollapse popup#include #include Global $skey = "blah123" ;Encryption key ; #FUNCTION# ==================================================================================================================== ; Name...........: SendData ; Description....: Send compress string using TCPSend() ; Syntax.........: SendData($iSock, $PacketSize, $sData, $msgBuffer, [1|0], n, [1|0], $progress) ; Parameters.....: $iSock - Socket ID ; $PacketSize - Size of receiving packets ; $sData - string to send ; $msgBuffer - Buffer storage for incoming data ; $iEncrytion - true|false to encryption $sData ; $iRetry - the number of time to retry sending data ; $iConfirmation - true|false if data is expected to be return from recipiant ; $progress - $progressbar id from GUICtrlCreateProgress() if used ; Return values..: Success: The uncompress data from ReceiveData() function ; Failure: -1 if error from socket ; 0 if $msgBuffer is not empty ; Remarks........: if string len of $sData < 100, the compressed binary size of $sData may be larger than original uncompressed ; Author.........: l4tran ; =============================================================================================================================== Func SendData(ByRef $iSock, $PacketSize, $sData, ByRef $msgBuffer, $iEncrypt = 0, $iRetry = 3, $iConfirmation = 0, $progress = 0) Local $aData[1] Local $sRecv = "" local $iSplitSize = 1000 $msgBuffer &= TCPRecv($iSock,$PacketSize) ;check status of socket and check for incoming data if @error Then $iSock = -1 ConsoleWrite("Resetting Sock:"&$iSock&" to -1"&@crlf) return -1 EndIf if $msgBuffer <> "" then return 0 ;do not send if there are incoming data $iCompressionBefore = BinaryLen(StringToBinary($sData)) $sData=Compress($sData) ;compression $sData using UDF from trancexx $iCompressionAfter = BinaryLen($sData) ;display compression ratio ConsoleWrite(@crlf&"Compression ratio: "&$iCompressionBefore&':'&$iCompressionAfter&" Percentage: "&100-Round($iCompressionAfter/$iCompressionBefore*100,2)&'%'&@CRLF) If $iEncrypt = 1 Then $sData = _StringEncrypt(1, $sData, $skey) ;Encrypt string if true If StringLen($sData) > $iSplitSize Then ;Split $sData into elements of string size 1000 and store it into an array While StringLen($sData) > $iSplitSize ReDim $aData[UBound($aData) + 1] $aData[UBound($aData) - 2] = StringLeft($sData, $iSplitSize) $sData = StringTrimLeft($sData, $iSplitSize) WEnd EndIf $aData[UBound($aData) - 1] = $sData If $iRetry = 0 Then Return 0 For $i = 0 To UBound($aData) - 1 ;Starting sending each element in the array GUICtrlSetData($progress, Round($i / (UBound($aData) - 1) * 100)) ConsoleWrite(".") ;send confirmation string | Encryption status | element of $sData | and iConfirmation bit TCPSend($iSock, UBound($aData) - 1 & '~' & $i & '~' & $iEncrypt & '~' & $aData[$i] & '~' & $iConfirmation & @CRLF) $ConfirmSent = TimerInit() Do ;Check from recipiant if each element is received. $sRecv = TCPRecv($iSock, $PacketSize) If TimerDiff($ConfirmSent) > 2500 Then ExitLoop ;wait 2.5 seconds for return packet confirmation before attempting to resend element Until ($sRecv = UBound($aData) - 1 & '~' & $i) If $sRecv <> UBound($aData) - 1 & '~' & $i Then ;check for confirmation string from recipiant; confirmation string = size of array & current counter ConsoleWrite(".") ;retry sending SendData($iSock, $PacketSize, $aData[$i], $msgBuffer, $iEncrypt = 0, $iRetry - 1, $iConfirmation, $progress) EndIf $sRecv = "" Next If $iConfirmation Then ;check if data is to be returned from recipiant $ConfirmSent = TimerInit() Do $sData = ReceiveData($iSock, $PacketSize, $msgBuffer, $progress) If TimerDiff($ConfirmSent) > 20000 Then ExitLoop Until ($sData) ;check for confirmation sent request has completed Return $sData ;return data that was sent back from recipiant EndIf EndFunc ;==>SendData Func getPacket($iSock, $PacketSize, ByRef $msgBuffer) $sRecv = TCPRecv($iSock, $PacketSize) If $sRecv <> "" Then $msgBuffer &= $sRecv EndIf If StringInStr($msgBuffer, @CRLF) Then ;ConsoleWrite($msgBuffer & @CRLF) If StringInStr($msgBuffer, '~') Then $aMsgRecv = StringSplit($msgBuffer, '~') $msgBuffer = "" Return $aMsgRecv EndIf EndIf EndFunc ;==>getPacket ; #FUNCTION# ==================================================================================================================== ; Name...........: ReceiveData ; Description....: Receive compress string from TCPRecv() ; Syntax.........: ReceiveData($iSock, $PacketSize, ByRef $msgBuffer, $progress = 0) ; Parameters.....: $iSock - Socket ID ; $PacketSize - Size of receiving packets ; $msgBuffer - Buffer storage for incoming data ; $progress - $progressbar id from GUICtrlCreateProgress() if used ; Return values..: Success: The uncompress data from ReceiveData() function ; Failure: 0 if receiving data is not formatted properly ; Remarks........: if string len of $sData < 100, the compressed binary size of $sData may be larger than original uncompressed ; Author.........: l4tran ; =============================================================================================================================== Func ReceiveData($iSock, $PacketSize, ByRef $msgBuffer, $progress = 0) Local $aData[1], $iSize = 1, $iCounter = 0 $aMsgRecv = getPacket($iSock, $PacketSize, $msgBuffer) ;get first element of array to determine the size of array If IsArray($aMsgRecv) Then If UBound($aData) - 1 <> $aMsgRecv[1] Then ReDim $aData[$aMsgRecv[1] + 1] ;resizing array based on confirmation string $aData[$aMsgRecv[2]] = $aMsgRecv[4] ;adding first element into array TCPSend($iSock, $aMsgRecv[1] & '~' & $aMsgRecv[2]) ;send confirmation string back to sender; packet received successfully If $aMsgRecv[1] > 0 Then Do ;completing the rest of array $aMsgRecv = getPacket($iSock, $PacketSize, $msgBuffer) ;getting more element of array If IsArray($aMsgRecv) Then If $progress <> 0 Then GUICtrlSetData($progress, Round($iCounter / $iSize * 100, 0)) ;Update progress bar status $iSize = $aMsgRecv[1] ;Size of array $iCounter = $aMsgRecv[2] ;Current counter $aData[$iCounter] = $aMsgRecv[4] TCPSend($iSock, $aMsgRecv[1] & '~' & $aMsgRecv[2]) ;send confirmation string back to sender; packet received successfully EndIf Until ($iSize = $iCounter) ;complete until counter reaches size of array EndIf EndIf $sData = "" ;convert array back to string For $i = 0 To UBound($aData) - 1 $sData &= $aData[$i] Next If IsArray($aMsgRecv) Then ;check if string needs to be decrypted before returning If $aMsgRecv[3] = 1 Then Return BinaryToString(Decompress(_StringEncrypt(0,$sData, $skey))) & '|' & $aMsgRecv[5] ElseIf $aMsgRecv[3] = 0 Then Return BinaryToString(Decompress($sData)) & '|' & $aMsgRecv[5] EndIf EndIf $aMsgRecv = 0 Return 0 EndFunc ;==>ReceiveData Func Compress($binString, $iCompressionStrength = 1) If Not IsBinary($binString) Then $binString = Binary($binString) Local $tCompressed Local $tSource = DllStructCreate('byte[' & BinaryLen($binString) & ']') DllStructSetData($tSource, 1, $binString) _WinAPI_LZNTCompress($tSource, $tCompressed, $iCompressionStrength) Local $bincompressed = DllStructGetData($tCompressed, 1) $tSource = 0 Return Binary($bincompressed) EndFunc ;==>Compress Func Decompress($binString) If Not IsBinary($binString) Then $binString = Binary($binString) Local $tSource = DllStructCreate('byte[' & BinaryLen($binString) & ']') DllStructSetData($tSource, 1, $binString) Local $tDecompress _WinAPI_LZNTDecompress($tSource, $tDecompress) $tSource = 0 Local $bString = Binary(DllStructGetData($tDecompress, 1)) Return $bString EndFunc Func _WinAPI_LZNTDecompress(ByRef $tInput, ByRef $tOutput, $iBufferSize = 0x800000) Local $tBuffer, $Ret $tOutput = 0 $tBuffer = DllStructCreate('byte[' & $iBufferSize & ']') If @error Then Return SetError(1, 0, 0) $Ret = DllCall('ntdll.dll', 'uint', 'RtlDecompressBuffer', 'ushort', 0x0002, 'ptr', DllStructGetPtr($tBuffer), 'ulong', $iBufferSize, 'ptr', DllStructGetPtr($tInput), 'ulong', DllStructGetSize($tInput), 'ulong*', 0) If @error Then Return SetError(2, 0, 0) If $Ret[0] Then Return SetError(3, $Ret[0], 0) $tOutput = DllStructCreate('byte[' & $Ret[6] & ']') If Not _WinAPI_MoveMemory(DllStructGetPtr($tOutput), DllStructGetPtr($tBuffer), $Ret[6]) Then $tOutput = 0 Return SetError(4, 0, 0) EndIf Return $Ret[6] EndFunc ;==>_WinAPI_LZNTDecompress ; #FUNCTION# ==================================================================================================================== ; Name...........: _WinAPI_LZNTCompress ; Description....: Compresses an input data. ; Syntax.........: _WinAPI_LZNTCompress ( $tInput, ByRef $tOutput [, $fMaximum] ) ; Parameters.....: $tInput - "byte[n]" or any other structure that contains the data to be compressed. ; $tOutput - "byte[n]" structure that is created by this function, and contain the compressed data. ; $fMaximum - Specifies whether use a maximum data compression, valid values: ; |TRUE - Uses an algorithm which provides maximum data compression but with relatively slower performance. ; |FALSE - Uses an algorithm which provides a balance between data compression and performance. (Default) ; Return values..: Success - The size of the compressed data, in bytes. ; Failure - 0 and sets the @error flag to non-zero, @extended flag may contain the NTSTATUS code. ; Author.........: trancexx ; Modified.......: Yashied, UEZ ; Remarks........: The input and output buffers must be different, otherwise, the function fails. ; Related........: ; Link...........: @@MsdnLink@@ RtlCompressBuffer ; Example........: Yes ; =============================================================================================================================== Func _WinAPI_LZNTCompress(ByRef $tInput, ByRef $tOutput, $fMaximum = True) Local $tBuffer, $tWorkSpace, $Ret Local $COMPRESSION_FORMAT_LZNT1 = 0x0002, $COMPRESSION_ENGINE_MAXIMUM = 0x0100 If $fMaximum Then $COMPRESSION_FORMAT_LZNT1 = BitOR($COMPRESSION_FORMAT_LZNT1, $COMPRESSION_ENGINE_MAXIMUM) $tOutput = 0 $Ret = DllCall('ntdll.dll', 'uint', 'RtlGetCompressionWorkSpaceSize', 'ushort', $COMPRESSION_FORMAT_LZNT1, 'ulong*', 0, 'ulong*', 0) If @error Then Return SetError(1, 0, 0) If $Ret[0] Then Return SetError(2, $Ret[0], 0) $tWorkSpace = DllStructCreate('byte[' & $Ret[2] & ']') $tBuffer = DllStructCreate('byte[' & (2 * DllStructGetSize($tInput)) & ']') $Ret = DllCall('ntdll.dll', 'uint', 'RtlCompressBuffer', 'ushort', $COMPRESSION_FORMAT_LZNT1, 'ptr', DllStructGetPtr($tInput), 'ulong', DllStructGetSize($tInput), 'ptr', DllStructGetPtr($tBuffer), 'ulong', DllStructGetSize($tBuffer), 'ulong', 4096, 'ulong*', 0, 'ptr', DllStructGetPtr($tWorkSpace)) If @error Then Return SetError(3, 0, 0) If $Ret[0] Then Return SetError(4, $Ret[0], 0) $tOutput = DllStructCreate('byte[' & $Ret[7] & ']') If Not _WinAPI_MoveMemory(DllStructGetPtr($tOutput), DllStructGetPtr($tBuffer), $Ret[7]) Then $tOutput = 0 Return SetError(5, 0, 0) EndIf Return $Ret[7] EndFunc ;==>_WinAPI_LZNTCompress Func _WinAPI_MoveMemory($pDestination, $pSource, $iLenght) DllCall('ntdll.dll', 'none', 'RtlMoveMemory', 'ptr', $pDestination, 'ptr', $pSource, 'ulong_ptr', $iLenght) If @error Then Return SetError(1, 0, 0) Return 1 EndFunc ;==>_WinAPI_MoveMemory Edited December 4, 2012 by l4tran Link to comment Share on other sites More sharing options...
chandoi Posted December 23, 2012 Share Posted December 23, 2012 very good Link to comment Share on other sites More sharing options...
caleb41610 Posted December 24, 2012 Author Share Posted December 24, 2012 (edited) very good ThanksHope it helpedAnd hope it helps others as well, I decided to drop this since I no long have a need for it and I'm moving on to c++edit: Added the latest *updates*it is unfinished. but it has some nice features. Includes remote screenshot and the start of a chatbox.ClientExample.au3Server.au3 Edited December 24, 2012 by caleb41610 chandoi 1 Multi-Connection TCP Server Link to comment Share on other sites More sharing options...
chandoi Posted January 6, 2013 Share Posted January 6, 2013 well, very useful Link to comment Share on other sites More sharing options...
tatane Posted February 12, 2015 Share Posted February 12, 2015 (edited) Hi. Thanks for your scripts. It works pretty well but I have a problem with the _CheckBadConnection(). I change your script to fit the new return error code from TCPRecv (in _CheckNewPackets() function): $RecvPacket = TCPRecv($Connection[$i][0], $PacketSize) ; on essaye de recevoir des données If $RecvPacket <> "" Then ; Si on reçoit des données... $Connection[$i][2] &= $RecvPacket ; On les ajoute au buffer de paquets Else If @error = -1 Then ContinueLoop EndIf If @error And @error <> -1 Then ; Si on a une erreur, la connexion est probablement coupée _CheckBadConnection() ; on vérifie donc EndIf EndIf and even if the client is disconnected (computer is offline) the @error is always equal to -1 so the disconnected client is not remove from the main array and listview (_CheckBadConnection() not call). How is it possible ? Edited February 12, 2015 by tatane Link to comment Share on other sites More sharing options...
MikahS Posted February 12, 2015 Share Posted February 12, 2015 (edited) I decided to drop this since I no long have a need for it and I'm moving on to c++ Â I'm thinking you might not get a reply from OP. Edited February 12, 2015 by MikahS Snips & Scripts My Snips: graphCPUTemp ~ getENVvarsMy Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4 Feel free to use any of my code for your own use. Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Forum FAQ Â Link to comment Share on other sites More sharing options...
tatane Posted February 12, 2015 Share Posted February 12, 2015 Maybe someone else who tried it ? Link to comment Share on other sites More sharing options...
ImOracle Posted February 12, 2015 Share Posted February 12, 2015 port 1337 are you serious? xD Link to comment Share on other sites More sharing options...
topten Posted April 29, 2015 Share Posted April 29, 2015 Thank you very much for your udf. It is really great!. Something what I can't understand. For example we have clients A,B,C simultaneously connected to the server. And the server is sending them some data (for example png). How does it happen? Is the server sending some piece of data to client A, to client B then to client C and then again to A, to B to C? or the clients B, C, are waiting when the server sends full data to A, then to B and then to C? What is the most effective way of dealing with multitasking? (for example sending picture to A, sending text message to B, sending binary to C? Great thanx in advance! Link to comment Share on other sites More sharing options...
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