Tjalve Posted November 8, 2014 Share Posted November 8, 2014 Hello everyone. I have been coding a bit in Autoit for the past year and i think that ive gotten faily good at it. However i have never read anything about Programming or done any serius programming befor this. So everying that i know is trail and error on my part. Now. I want to try to create a small server/agent program that can help me inventory a small number of computers. I know that that sort of program already exists but i want to challenge myself and try to do it myself. In the end i want to be able to have a server with a small console witch tell me witch computers are on, and then be able to send "commands" to the agents. I did a bit of coding yesterday and i used Wayfarer EXELENT server example ('?do=embed' frameborder='0' data-embedContent>>) and i think i understand most of the code. But there is still one thing that eludes me. And its TCP_Send and TCP_Recv. When you use TCP_Send, yopu send a string (or a set of binary data) to a specific IP usinga specific port. That mutch i understand. But what i dont understand is how TCP_Recv grabs this information. I mean, if I call TCP_Recv after I ve send the data on the other end, i ghet nothing. But if i use an infinite loop and call TCP_Recv once every 5-10ms then i get the data on the other end. So my question is, how often do i need to listen? And what heppends if the servicer just happen "not to listen" just when the client sends the data. Isnt there a chance that i might loose some data in transit? Or is there some kind of buffer that can be read? I know that all this is working Wayfarers example, but i want to be able to write the code myself and i want to understand how this works. Anyone willing te give me a quick explanation? Link to comment Share on other sites More sharing options...
Celtic88 Posted November 8, 2014 Share Posted November 8, 2014 here is an example I hope will helps you Server expandcollapse popupOpt("GUIONEVENTMODE", 1) GUICreate("Form1", 475, 304) GUISetOnEvent(-3, "_EXITdb") Global $Edit1 = GUICtrlCreateEdit("", 8, 8, 329, 241) Global $Input1 = GUICtrlCreateInput("", 24, 264, 180, 21) GUICtrlCreateButton("Send", 208, 264, 47, 25) GUICtrlSetOnEvent(-1, "_Senddata") GUICtrlCreateLabel("Select socket ", 360, 8, 70, 17) Global $List1 = GUICtrlCreateListView("Socket list", 352, 32, 113, 253) GUISetState(@SW_SHOW) TCPStartup() _Consolwrite("-> listener started on port : " & 403 & " <-") Global $TCPL = TCPListen(@IPAddress1, 403) If @error Then Exit Global $arrayclien[1][3] Global $Packmsg = "[Msgpack]" Global $Packend = "[Endpack]" Func _TCPAccept() Local $TCPA = TCPAccept($TCPL) If $TCPA = -1 Then Return Do $res = TCPRecv($TCPA, 50) Until $res <> "" _Sptpack($res, $TCPA) ReDim $arrayclien[$arrayclien[0][0] + 2][3] $arrayclien[0][0] += 1 $arrayclien[$arrayclien[0][0]][0] = $TCPA $arrayclien[$arrayclien[0][0]][1] = GUICtrlCreateListViewItem($TCPA, $List1) _Consolwrite("-> New connection socket : " & $TCPA & " <-") EndFunc ;==>_TCPAccept Local $Resv, $TCPR, $TCPRtmp While 1 Sleep(10);; _TCPAccept() For $oi = 1 To $arrayclien[0][0] If $oi > $arrayclien[0][0] Then ExitLoop ;;; $Resv = _TCPRecv($arrayclien[$oi][0], 20) Next WEnd Func _Consolwrite($txt) GUICtrlSetData($Edit1, GUICtrlRead($Edit1) & $txt & @CRLF) EndFunc ;==>_Consolwrite Func _TCPRecv($Soker, $Len) $TCPR = TCPRecv($Soker, $Len) If @error Then _Consolwrite("-> Client has been disconnected : " & $Soker & " <-") _Dellclien($Soker) EndIf $TCPRtmp = $TCPR If $TCPR = "" Then Return $TCPRtmp Do $TCPR = TCPRecv($Soker, $Len) If $TCPR = "" Then ExitLoop $TCPRtmp &= $TCPR Until $TCPR = "" _Sptpack($TCPRtmp, $Soker) EndFunc ;==>_TCPRecv Func _Sptpack($mPack, $Soker) Local $Splitpack = StringSplit($mPack, $Packend, 1) If @error Then Return For $ii = 0 To $Splitpack[0] _Getpacktyp($Splitpack[$ii], $Soker) Next EndFunc ;==>_Sptpack Func _Getpacktyp($mPack, $Msoket) Select Case StringInStr($mPack, $Packmsg) > 0 _Consolwrite($Msoket & " Say : " & StringTrimLeft($mPack, StringInStr($mPack, $Packmsg) + StringLen($Packmsg) - 1)) ; Case StringInStr($mPack, $PackSendifle) > 0 EndSelect EndFunc ;==>_Getpacktyp Func _TCPSend($Soker, $mdata) TCPSend($Soker, $mdata) EndFunc ;==>_TCPSend Func _Senddata() If GUICtrlRead(GUICtrlRead($List1)) = "" Then _Consolwrite("-> Please select a socket first <-") Return EndIf If GUICtrlRead($Input1) = "" Then Return _TCPSend(GUICtrlRead(GUICtrlRead($List1)), $Packmsg & GUICtrlRead($Input1) & $Packend) EndFunc ;==>_Senddata Func _Dellclien($Soket) Dim $Arryctmp[$arrayclien[0][0]][3], $i For $oi = 1 To $arrayclien[0][0] If $Soket = $arrayclien[$oi][0] Then GUICtrlDelete($arrayclien[$oi][1]) ContinueLoop EndIf $i += 1 For $m = 0 To 2 $Arryctmp[$i][$m] = $arrayclien[$oi][$m] Next Next $Arryctmp[0][0] = $arrayclien[0][0] - 1 $arrayclien = $Arryctmp EndFunc ;==>_Dellclien Func _EXITdb() TCPShutdown() Exit EndFunc ;==>_EXITdb Client expandcollapse popupOpt("GUIONEVENTMODE", 1) GUICreate("Form1", 345, 304) GUISetOnEvent(-3, "_EXITdb") Global $Edit1 = GUICtrlCreateEdit("", 8, 8, 329, 241) Global $Input1 = GUICtrlCreateInput("", 24, 264, 225, 21) GUICtrlCreateButton("Send", 268, 264, 47, 25) GUICtrlSetOnEvent(-1, "_Senddata") GUISetState(@SW_SHOW) TCPStartup() Global $TCPL Global $Packmsg = "[Msgpack]" Global $Packend = "[Endpack]" _TCPConnect() Func _TCPConnect() _Consolwrite("-> connection was started wait for response <-") While 1 $TCPL = TCPConnect(@IPAddress1, 403) If $TCPL <> -1 Then ExitLoop WEnd _Consolwrite("-> A connection was successfully established with the server <-") _TCPSend($TCPL, $Packmsg & "Hallo :)" & $Packend) EndFunc ;==>_TCPConnect Local $Resv, $TCPR, $TCPRtmp While 1 Sleep(10) _TCPRecv($TCPL, 20) WEnd Func _Consolwrite($txt) GUICtrlSetData($Edit1, GUICtrlRead($Edit1) & $txt & @CRLF) EndFunc ;==>_Consolwrite Func _TCPRecv($Soker, $Len) $TCPR = TCPRecv($Soker, $Len) If @error Then _Consolwrite("-> Server has been shut down <-") _TCPConnect() EndIf $TCPRtmp = $TCPR If $TCPR = "" Then Return $TCPRtmp Do $TCPR = TCPRecv($Soker, $Len) If $TCPR = "" Then ExitLoop $TCPRtmp &= $TCPR Until $TCPR = "" _Sptpack($TCPRtmp) EndFunc ;==>_TCPRecv Func _Sptpack($mPack) Local $Splitpack = StringSplit($mPack, $Packend, 1) If @error Then Return For $ii = 0 To $Splitpack[0] _Getpacktyp($Splitpack[$ii]) Next EndFunc ;==>_Sptpack Func _Getpacktyp($mPack) Select Case StringInStr($mPack, $Packmsg) > 0 _Consolwrite("Server Say : " & StringTrimLeft($mPack, StringInStr($mPack, $Packmsg) + StringLen($Packmsg) - 1)) ;Case StringInStr($mPack, $PackSendifle) > 0 EndSelect EndFunc ;==>_Getpacktyp Func _TCPSend($Soker, $mdata) TCPSend($Soker, $mdata) EndFunc ;==>_TCPSend Func _Senddata() If GUICtrlRead($Input1) = "" Then Return _TCPSend($TCPL, $Packmsg & GUICtrlRead($Input1) & $Packend) EndFunc ;==>_Senddata Func _EXITdb() TCPShutdown() Exit EndFunc ;==>_EXITdb Link to comment Share on other sites More sharing options...
Tjalve Posted November 8, 2014 Author Share Posted November 8, 2014 I thank you. But i already have working examples. Burt i want to understand how it works. Why do you need to have TCP_recv in a loop to be able to get the data? Link to comment Share on other sites More sharing options...
Kyan Posted November 8, 2014 Share Posted November 8, 2014 I thank you. But i already have working examples. Burt i want to understand how it works. Why do you need to have TCP_recv in a loop to be able to get the data? Because you won't receive 400 or 50 or 1 MB in 1ms Heroes, there is no such thing One day I'll discover what IE.au3 has of special for so many users using it.C'mon there's InetRead and WinHTTP, way better Link to comment Share on other sites More sharing options...
Tjalve Posted November 8, 2014 Author Share Posted November 8, 2014 Because you won't receive 400 or 50 or 1 MB in 1ms Of course i know that. I just wish someone could tell me how it works. Link to comment Share on other sites More sharing options...
BrewManNH Posted November 8, 2014 Share Posted November 8, 2014 Maybe, you should explain what it is you're having difficulties understanding, rather than just throwing up your hands and saying "I don't get it". If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
ripdad Posted November 9, 2014 Share Posted November 9, 2014 (edited) For $i = 1 To 200 $sRecv = TCPRecv($nSocket, 1024); <- Maximum bytes to receive. If @error Then ExitLoop ElseIf $sRecv <> '' Then $sBuffer &= $sRecv If StringRight($sRecv, 4) = @CRLF & @CRLF Then; <- EOF (End Of File) ExitLoop EndIf $i = 0; <- reset timeout EndIf Sleep(10) Next ; Do something with $sBuffer at this point. In the example above, TCPRecv() will receive data at a rate up to 1024 bytes per call. If you sent a file that was 10KB's in size, it would take at least 10 turns of the loop to receive all the data. You might think you could increase the maximum bytes to 10240 to receive the file in one call, but it just doesn't work that way. In reality, the behavior behind the scenes, goes something like this: Loop# 1 = blank 2 = 1024 bytes received 3 = blank 4 = 512 bytes received 5 = 1024 bytes received 6 = 256 bytes received 7 = blank 8 = 1024 bytes received 9 = etc, etc. So this is the reason you need a loop to receive data. You should always use some type of escape method when using loops of this nature, so that your script won't get stuck there when something goes wrong. I personally use a For loop as a timeout gimmick (see example). For more information than you really want to know, see MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx Edited November 9, 2014 by ripdad "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward Link to comment Share on other sites More sharing options...
Tjalve Posted November 9, 2014 Author Share Posted November 9, 2014 For $i = 1 To 200 $sRecv = TCPRecv($nSocket, 1024); <- Maximum bytes to receive. If @error Then ExitLoop ElseIf $sRecv <> '' Then $sBuffer &= $sRecv If StringRight($sRecv, 4) = @CRLF & @CRLF Then; <- EOF (End Of File) ExitLoop EndIf $i = 0; <- reset timeout EndIf Sleep(10) Next ; Do something with $sBuffer at this point. In the example above, TCPRecv() will receive data at a rate up to 1024 bytes per call. If you sent a file that was 10KB's in size, it would take at least 10 turns of the loop to receive all the data. You might think you could increase the maximum bytes to 10240 to receive the file in one call, but it just doesn't work that way. In reality, the behavior behind the scenes, goes something like this: Loop# 1 = blank 2 = 1024 bytes received 3 = blank 4 = 512 bytes received 5 = 1024 bytes received 6 = 256 bytes received 7 = blank 8 = 1024 bytes received 9 = etc, etc. So this is the reason you need a loop to receive data. You should always use some type of escape method when using loops of this nature, so that your script won't get stuck there when something goes wrong. I personally use a For loop as a timeout gimmick (see example). For more information than you really want to know, see MSDN:http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx That was EXACTLY what i was looking for. Thank you ripdad. I will read trough the MSDN article. So basicly if i use TCP_Send to send 1MB of data, i will need to use TCPRecv at least 10 times to get the whole data. So if there are several clients sending data at the same time, how do you know what data goes where (since it gets chopped up). Or if the same client first send one file of 800KB and then another file with 2KB and then another one at 3MB. How do you know when the file "start" and "end"? I guess i need to create some kind of buffer to be able to handle bigger data. One other question. Is there any best practises regarding the size? Is 1024 a good number or is 2048 better? And why would one be better then the other? Thank you again. Link to comment Share on other sites More sharing options...
ripdad Posted November 9, 2014 Share Posted November 9, 2014 (edited) So basicly if i use TCP_Send to send 1MB of data, i will need to use TCPRecv at least 10 times to get the whole data. Yep, If you set max bytes (or max length) to 102400. At 10240, 1MB of data would take a minimum of 100 turns. So if there are several clients sending data at the same time, how do you know what data goes where (since it gets chopped up). Or if the same client first send one file of 800KB and then another file with 2KB and then another one at 3MB. How do you know when the file "start" and "end"? I guess i need to create some kind of buffer to be able to handle bigger data. There are many scripts in the examples section of the forum, that show you how to deal with multiple clients and the incoming data. I hope you are up to speed on using arrays. If not, then that would be a good place to start! One other question. Is there any best practises regarding the size? Is 1024 a good number or is 2048 better? And why would one be better then the other? Seems everyone has an opinion on this - but the research says the majority use 8192. Mainly because most website servers send data in 8192 byte chunks. Thank you again. Glad I could help. Edited November 9, 2014 by ripdad "The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward 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