Jump to content
Sign in to follow this  

TCPRecv idling the CPU, or is it just slow?

Recommended Posts

Hello, I've done some testing and I've noticed that TCPRecv is slow, but it's almost exactly 1ms each time it's called if the socket is a valid socket and not a dead socket...So this got me thinking about the line in the help file about TCPRecv idling the CPU, presumably to allow people to call it continuously inside an extremely tight loop without running the CPU usage up too bad. I've been making a chat client/server (which I won't bother posting since it seems just about everyone has made those, it would just be another fish in the sea) and I always wondered why in my stress-testing, it would conk out after around 300-350 separate clients and then the interpreter itself would lock up and fail to respond.

I think I've found out why it does this after some investigation into TCPRecv, what happens when too much data is buffered without flushing it with another call to TCPRecv (interpreter locking up), and ultimately why said chat server is limited to a few hundred clients...after some more testing, that delay gets to be pretty high the more clients the server caters to. If the server has 50 people on it, it's doing around 50ms of sleeps each time it loops through to check the clients just from the calls to TCPRecv..so once it gets around 300-350 clients on at once, it's waiting 300-350ms total each time it does a loop. This ends up delaying all clients connected by basically 1ms per client connected plus their actual latency to the server, which is not that good...

I know some people may think "If you want to have a server cater to that many connections in a timely fashion, you should use a different language..." but I'm really only doing this for the experience, I have no intentions of actually letting this stuff roam free in the wild :graduated:

Anywho, I figured I would test out trying to reinvent the wheel, to call the recv function in Ws2_32.dll and basically make my own version of TCPRecv that would work without the delay in it (assuming that 1ms time was an artificial delay put there by the AutoIt devs to idle the CPU) and see if that could do the job any faster...But that is when I started running in to the issue I am having right now, and where my lack of C/C++ knowledge is really starting to bite me in the behind.

Below is the function I tried making to emulate TCPRecv but failed at doing so...DllCall is setting @error to 1, which according to the help file says it was unable to access the dll, but I know from previous experience that AutoIt has no problem using Ws2_32.dll (the function _SocketToIP that has been floating around here for ages is one semi-well known one that calls this dll) so I'm guessing it's an issue with my lack of experience in the dark side of AutoIt so to speak...

Func _TCPRecv($iSock, $iLen)
Local $structBuffer = DllStructCreate("char[" & $iLen & "]")
Local $aRet = DllCall("Ws2_32.dll", "int", "recv", "int", $iSock, "char", DllStructGetPtr($structBuffer), "int", $iLen, "int", 0)
If @error Then SetError(1, 0, "")
Return SetError(0, $aRet[0], DllStructGetData($structBuffer, 1))

Any insight about TCPRecv's delay or my failed attempt at reinventing the wheel would be greatly apriciated! ;)

Share this post

Link to post
Share on other sites

"char" should be "ptr"

Might use byte struct instead of a char one.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post

Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • By algiuxas
      Hello everybody,
      I'm making an program witch reads packets from server/client, first of all it reads size of the packet(it may be 1-5 bytes in size), and then reads what's left.

      Problem: TCPRecv($socket,1,1) tooks really long to receive 1 byte, most of the time 100ms!
      You can see packets here and how much time it took to read size of them(1-5 bytes, all of them are 1 byte in size): 0xAA63 (99.8802703210873ms) 0x53 (99.8829718030123ms) 0x2B (99.7435753356861ms) 0x4E (100.176352740059ms) I want to interrupt sometimes server or client, send packets, but I cannot send packets if server/client didn't get last packet. Sometimes packets are huge(16MB or even more), sometimes they are 2-6 bytes in size. I just don't want to receive everything and just send it. I want to see every packet, and collect data from these packets.
      EDIT: I receive couple packets at the same time with TCPRecv to make it faster. I use TCPRecv($socket,10000,1). It made program a bit faster... But still, when receiving again these packets, it still tooks 100ms. It's still slow.

      How to make TCPRecv($socket,1,1) faster? I don't need any error checking or etc., just to make it as fast as possible. (I only receive everything in hexadecimal)

      I really need help with this... It's so slow and annoying!
    • By LoadStar
      I am trying to listen to a connection over telnet... I can send data, but I am having trouble finding a solution to receiving a response. Here is what I am working on:
      #include <GUIConstants.au3> #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <ListViewConstants.au3> #include <ProgressConstants.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <File.au3> #include <GuiListView.au3> #include <EditConstants.au3> HotKeySet("{INSERT}", "_easteregg") HotKeySet("{F1}", "_debugwindow") Global $ainput Global $file = "C:\SimpleOpensClient\messages\messagequeue.txt" Global $time = "" Global $status_text = "" Global $lastaction_text = "No last action." Global $ChyronIP = tcpconnect("", "23") Global $TCPRecv = TCPRecv($ChyronIP,"5000") Global $debug_text = "" Global $section Global $time = @HOUR & ":" & @MIN & ":" & @SEC #Region ;~ Main Window $form1_1 = GUICreate("Simple Opens Client 1.5", 803, 529, 458, 314) $listview1 = GUICtrlCreateListView("Messages", 10, 120, 781, 401) GUICtrlSendMsg(-1, $lvm_setcolumnwidth, 0, 50) $listview1_0 = GUICtrlCreateListViewItem("aInput[i]", $listview1) $listview1_1 = GUICtrlCreateListViewItem("aInput[i]", $listview1) $button2 = GUICtrlCreateButton("Refresh", 10, 70, 250, 46) $button3 = GUICtrlCreateButton("Push Messages", 270, 70, 260, 45) $button4 = GUICtrlCreateButton("Clear", 540, 70, 250, 45) $label1 = GUICtrlCreateLabel("", 540, 10, 247, 42, $ss_center) GUICtrlSetFont(-1, 32, 400, 0, "MS Sans Serif") GUICtrlSetColor(-1, 65280) GUICtrlSetBkColor(-1, 0) GUICtrlSetResizing(-1, $gui_dockhcenter + $gui_dockvcenter) $status = GUICtrlCreateLabel("Status:" & $status_text, 10, 10, 517, 27) $lastaction = GUICtrlCreateLabel("Last Action:" & $lastaction_text, 10, 50, 520, 17) GUISetState(@SW_SHOW) _guictrllistview_setcolumnwidth($listview1, 0, 600) ;~ Easter egg $easteregg = GUICreate("Administrator Section", 251, 99, -1, -1) $passwordedit = GUICtrlCreateInput("password", 8, 32, 233, 21, $es_password) $buttonok = GUICtrlCreateButton("&OK", 86, 64, 75, 25) $buttoncancel = GUICtrlCreateButton("&Cancel", 167, 64, 75, 25) $enterpasslabel = GUICtrlCreateLabel("Enter password", 8, 12, 77, 17, 0) GUISetState(@SW_HIDE) ;~ Console Window $consolewindow = GUICreate("Debug Console", 674, 438, 340, 402, $WS_BORDER, @SW_HIDE) $consoledebug = GUICtrlCreateEdit("", 0, 0, 673, 417, BitOR($ES_WANTRETURN, $WS_VSCROLL, $ES_AUTOVSCROLL, $ES_READONLY)) GUICtrlSetData(-1, $debug_text) GUISetState(@SW_HIDE) #EndRegion TCPStartup() _get() WinActivate("Simple Opens Client 1.5", "") While 1 $status_text = "Idle." _writetostatus() $time = @HOUR & ":" & @MIN & ":" & @SEC GUICtrlSetData($label1, $time) Sleep(50) $nmsg = GUIGetMsg() Switch $nmsg Case $gui_event_close TCPShutdown() Exit Case $button2 $lastaction_text = "Refresh" GUICtrlSetData($lastaction, "Last Action: " & $lastaction_text & " @ " & $time) _get() Case $button3 $lastaction_text = "Push" GUICtrlSetData($lastaction, "Last Action: " & $lastaction_text & " @ " & $time) _pushmessages() Case $button4 $lastaction_text = "Clear" GUICtrlSetData($lastaction, "Last Action: " & $lastaction_text & " @ " & $time) _clear() Case $buttonok If GUICtrlRead($passwordedit) == "secret" Then $nbbo = GUICreate("NO BOOTY", 204, 206, 217, 145) $pic1 = GUICtrlCreatePic("\\\SimpleOpens\images\nbbo.bmp", 0, 0, 201, 201) GUISetState(@SW_SHOW) Sleep(5000) GUIDelete($nbbo) GUIDelete($easteregg) Else MsgBox(0, "Access Denied", "Incorrect password.") EndIf Case $buttoncancel GUIDelete($easteregg) EndSwitch WEnd Func _get() $section = "Get" _GUICtrlListView_DeleteAllItems($ListView1) $status_text = "Copying new information." _writetostatus() $UrlDownload = "" ;DL link $Directory = "C:\SimpleOpensClient\messages\messagequeue.txt" ;Name of your file FileDelete($Directory) Local $download = InetGet($UrlDownload, $Directory,0,1) Do Sleep(100) $debug_text = "[Get] Downloading messagequeue.txt from" _writetoconsole() Until InetGetInfo($download, 2) ;Checks to see if $download is completed (param 2) InetClose($download) RunWait($Directory) ;it will pause the script untill the process of the downloaded file is finished $debug_text = "[Get] Download finished." GUICtrlSetData($consoledebug, "[" & $time & "]" & " - " & $debug_text & @CRLF, 1) _filereadtoarray($file, $ainput) $status_text = "New information copied." _writetostatus() For $i = 1 To UBound($ainput) - 1 $status_text = "Writing information to list." GUICtrlSetData($status, "Status: " & $status_text) GUICtrlCreateListViewItem($ainput[$i], $listview1) Next EndFunc Func _clear() $section = "Clear" TCPStartup() $status_text = "Clearing data." _writetostatus() _guictrllistview_deleteallitems($listview1) $ChyronIP = tcpconnect("", "23") Do Sleep(100) $debug_text = "Trying to connect to Chyron..." _writetoconsole() Until $ChyronIP <> "-1" $debug_text = "Connected." _writetoconsole() TCPSend($ChyronIP, "E\Delete8000\\" & @CRLF) $debug_text = "Delete8000 sent." _writetoconsole() Sleep(100) $debug_text = ("Disconnecting...") _writetoconsole() TCPShutdown() $debug_text = ("Disconnected.") _writetoconsole() EndFunc Func _pushmessages() $section = "PushMessages" TCPStartup() $ChyronIP = tcpconnect("", "23") Do Sleep(100) $debug_text = "Trying to connect to Chyron..." _writetoconsole() Until $ChyronIP <> "-1" $debug_text = "Connected." _writetoconsole() TCPSend($ChyronIP, "E\Delete8000\\" & @CRLF) $debug_text = "Delete8000 sent." _writetoconsole() _filereadtoarray($file, $ainput) For $i = 1 To UBound($ainput) - 1 TCPSend($ChyronIP, $ainput[$i] & @CRLF) $debug_text = ("Sending: " & "''" & $ainput[$i] & "''") $status_text = ("Sending: " & $ainput[$i]) _writetostatus() _writetoconsole() Sleep(10) Next $debug_text = ("Disconnecting...") _writetoconsole() TCPShutdown() $debug_text = ("Disconnected.") _writetoconsole() EndFunc Func _easteregg() #Region ### START Koda GUI section ### Form= $easteregg = GUICreate("Administrator Section", 251, 99, -1, -1) $passwordedit = GUICtrlCreateInput("password", 8, 32, 233, 21, $es_password) $buttonok = GUICtrlCreateButton("&OK", 86, 64, 75, 25) $buttoncancel = GUICtrlCreateButton("&Cancel", 167, 64, 75, 25) $enterpasslabel = GUICtrlCreateLabel("Enter password", 8, 12, 77, 17, 0) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### EndFunc Func _writetostatus() GUICtrlSetData($status, "Status: " & $status_text) EndFunc Func _writetoconsole() GUICtrlSetData($consoledebug, "[" & $time & "]" & " - " & "[" & $section & "]" & " " &$debug_text & @CRLF, 1) EndFunc Func _debugwindow() If WinGetState($consolewindow, 7) = 7 Then WinSetState($consolewindow, "", @SW_HIDE) Return ElseIf WinGetState($consolewindow, 5) = 5 Then WinSetState($consolewindow, "", @SW_SHOW) WinActivate($form1_1) Return EndIf EndFunc The responses I am expecting is a "*" the server uses as an acknowledgement of the command.
      Should I create a new function and call it in the While loop? I would like to monitor the connections at all times if possible.
      Also tips on how to clear up this mess would be appreciated as well
    • By Rickname
      I downloaded FF.au3 , installed MozRepl, started it, put 4242 as port in it, then when Im trying to run this simple script :
      #include "FF.au3" _FFConnect(default,Default,6000) _FFWindowOpen("http://www.youtube.com", True, True) The thing is, it actually works, but it is still gives me a very annoying error :
      What can do ?
  • Create New...