Modify

Opened 4 years ago

Closed 3 years ago

Last modified 20 months ago

#2596 closed Bug (Fixed)

TCPRecv not returning data, and setting @error to -1

Reported by: diegomainster@… Owned by: Jon
Milestone: 3.3.13.2 Component: AutoIt
Version: 3.3.10.2 Severity: None
Keywords: Cc:

Description

Hello, sorry for my english, I'm using a translator.

I would like to inform that the TCPRecv is not returning data, and are setting @error to -1. I noticed this problem in version 3.3.10.0, updated today to version 3.3.10.2 and still continues. The problem is not in my notebook because it tested in another, and not in my script, it works with version 3.3.8.1. A script to test I'm using is this:

TCPStartup()
;if I set $ip with a local address or a nearby site, such as the provider, TCPRecv works most of the time, but sometimes not
$ip = TCPNameToIP('www.google.com')
If @error Then erro('TCPNameToIP', @error)
$tc = TCPConnect($ip, 80)
If @error Then erro('TCPConnect', @error)
TCPSend($tc, 'GET / HTTP/1.1' & @CRLF & 'Host: www.google.com' & @CRLF & 'Connection: close' & @CRLF & @CRLF)
If @error Then erro('TCPSend', @error, 1)
$tr = ''
$ti = TimerInit()
Do
   $tr &= TCPRecv($tc, 1)
   If @error Then erro('TCPRecv', @error, 1)
   If TimerDiff($ti) > 9999 Then erro('Timeout', '', 1)
Until StringInStr($tr, @CRLF & @CRLF)
MsgBox(0, 'Receive Header:', $tr)
$tr = ''
$ti = TimerInit()
While 1
   $tr &= TCPRecv($tc, 1480)
   If @error Or TimerDiff($ti) > 9999 Then ExitLoop
WEnd
MsgBox(0, 'Receive Content:', $tr)
TCPCloseSocket($tc)

Func erro($f, $e, $c = 0)
   MsgBox(16, 'Erro:', 'Function ' & $f & @LF & '@error = ' & $e)
   If $c Then TCPCloseSocket($tc)
   TCPShutdown()
   Exit
EndFunc

If I call the Sleep() before TCPRecv with a greater than or equal to 500ms time (sometimes works with a shorter time), the TCPRecv returns data, and not sets @error, as in the following script:

TCPStartup()
;if I set $ip with a local address or a nearby site, such as the provider, TCPRecv works most of the time, but sometimes not
$ip = TCPNameToIP('www.google.com')
If @error Then erro('TCPNameToIP', @error)
$tc = TCPConnect($ip, 80)
If @error Then erro('TCPConnect', @error)
TCPSend($tc, 'GET / HTTP/1.1' & @CRLF & 'Host: www.google.com' & @CRLF & 'Connection: close' & @CRLF & @CRLF)
If @error Then erro('TCPSend', @error, 1)
$tr = ''

;with sleep work
Sleep(500)

$ti = TimerInit()
Do
   $tr &= TCPRecv($tc, 1)
   If @error Then erro('TCPRecv', @error, 1)
   If TimerDiff($ti) > 9999 Then erro('Timeout', '', 1)
Until StringInStr($tr, @CRLF & @CRLF)
MsgBox(0, 'Receive Header:', $tr)
$tr = ''
$ti = TimerInit()
While 1
   $tr &= TCPRecv($tc, 1480)
   If @error Or TimerDiff($ti) > 9999 Then ExitLoop
WEnd
MsgBox(0, 'Receive Content:', $tr)
TCPCloseSocket($tc)

Func erro($f, $e, $c = 0)
   MsgBox(16, 'Erro:', 'Function ' & $f & @LF & '@error = ' & $e)
   If $c Then TCPCloseSocket($tc)
   TCPShutdown()
   Exit
EndFunc

Attachments (0)

Change History (47)

comment:1 Changed 4 years ago by Mat

I ran it in a loop counting the number of time it succeeded and failed, and it failed 10 times with that error in 1000 tests. (test code: http://pastie.org/8595004 output: http://pastie.org/8595005)

comment:2 Changed 4 years ago by anonymous

If I test with an "IP / site" my country, the results are similar to yours, but if the "IP / site" is from another country (I think for the ping be higher), the tests I did with the changes you made, 100% @ error = -1.

Test with an "IP / site" with a higher ping. I think the problem is these new versions, as in 3.3.8.1 does not have this problem.

My test result: http://pastebin.com/rqKj0KqC
The same test in version 3.3.8.1: http://pastebin.com/fcBMNdAJ

comment:3 Changed 4 years ago by Mat

I tried it with www.gov.au as I figured it wouldn't get further away than australia. Ping() would occasionally fail with @error = 2, but would mostly return around 340ms. TCPRecv failed with -1 every time. Adding a 500ms sleep between sending and receiving works.

So TCPRecv needs to be changed to wait for data (with timeout?) or does TCPSend need to be modified to wait for a reply before returning success?

comment:4 Changed 4 years ago by diegomainster@…

I think I found a temporary solution to this problem:

If I replace the code below the first TCPRecv

If @error Then erro('TCPRecv', @error, 1)

by that:

If @error = -1 Then
	Sleep(100)
ElseIf @error Then
	erro('TCPRecv', @error, 1)
EndIf

the data is returned in the next call to TCPRecv. So I think @error = -1 does not mean a serious error or that the socket was closed, I think it just means that the socket is not ready to receive data.

comment:5 Changed 4 years ago by garbb

I was having the same problem. It seems that TCPRecv() is now setting @error=-1 in different situations in v3.3.10.2 than it was in v3.3.8.1. Like you say, -1 is not a fatal error, it just means that it it waiting/not ready. I tested forcibly disconnecting a connection I made with a v3.3.10.2 script using external software and got @error=10054 which is "connection reset by peer" so it is setting @error as it was in v3.3.8.1 other than the -1 thing.

comment:6 Changed 4 years ago by garbb

After experimenting with this a bit more it seems that TCPRecv() will just set @error=-1 when it has no data to return (when the tcp buffer is empty?)

This is probably why when you add a delay after sending with TCPSend() you will not get @error=-1. You have allowed enough time to pass for the server to return some data and the TCP buffer to be filled.

So really the issue here is an undocumented change to the way that TCPRecv() works (what it sets @error to in what cases)

If you simply change your error handling to only check for @error>0 after a TCPRecv call then it should work as in v3.3.8.1

comment:7 Changed 4 years ago by musiqueGraeme

I have found the same problem with UDPRecv returning the error -1 when empty. I have set the error handling to ignore error=-1.

comment:8 Changed 4 years ago by anonymous

Is it possible to revert this behavior back to the v3.3.8.1 state? It was useful in detecting a closed socket on the other end. Thank you.

comment:9 Changed 4 years ago by anonymous

TCPRecv is horribly degraded by new update version. Setting @ERROR for blank returns has no practical use as far as I can tell, and only harms the process. TCPRecv needs to be able to detect client side closed sockets as older versions of TCPRecv were able to do. Don't know why @error -1 is set for blank returns and if it needs to be that way then fine, (have no idea why), but please let there be some kind of error setting that can detect client side closed sockets. @error -1 for detecting client side closed sockets was invaluable to TCPRecv heavy scripts and I can not use newer versions of Autoit3 in those scripts because the older TCPRecv is many times over more efficient than the newer versions.

comment:10 Changed 4 years ago by anonymous

Ignoring @error -1 does not make TCPRecv mimic v3.3.8.1. It is still less effective than the genuine TCPRecv version 3.3.8.1. (Can't detect client side closed sockets is the nasty issue)

I've tested ignoreing -1 @errors and whatever errors are left can't detect closed client side sockets. This is very bad for servers that respond to web browser requests.

comment:11 Changed 4 years ago by Jpm

When I try to add the TCPConnect timeout I found that the @error set -1 for different case.
SO I modify the @error to identify uniquely the error.
In your case I main error come frome the fact that TCPConnect return timeout When the error occurs

You can find an updated version of Autoit3.exe at

http://www.autoitscript.com/autoit3/devs/jpm/#2384_UDPTCP_@error/

The .txt describe the change in @error
Just play with and report any comments

Thanks for your cooperation
Jpm

comment:12 Changed 4 years ago by anonymous

If I understand what I'm reading then this code should work to detect client side closed sockets but my tests say that the beta still can't detect client side closed sockets.

Downloaded the beta .exe from the link and updated my old exe.
Problem returns just as I remember it. Sorry... I can't think of any other solutions but to revert back to the older version.

This is what i'm using.

$tcprecvmessg = TCPRecv($recvsockets,$tcpmaxbitss,1)
If @error < -1 Or @error > 0 Then ; Still can't detect client side closed sockets

Thank you for your time.

comment:13 Changed 4 years ago by Jpm

If you use the repro script I uploaded does the error occured on the TCPConnect() not on the TCPRecv()?

comment:14 Changed 4 years ago by FixTCPRecvForNewVersions

Not exactly sure what i'm suppose to do with that. But this is what I did. Installed the beta version you have there, then ran the repro script and this is what it came out with.

getting info -> @error = -3 @extended = 3

comment:15 Changed 4 years ago by Jpm

Sorry, I forget to upload your repro script a liitle bit modified
#2596 TCPRecv @error.au3
try with this new upload and you will see I think the TCPConnect() error

comment:16 Changed 4 years ago by FixTCPRecvForNewVersions

First time running the script get @error 10060 then counts @error -1 forever. All attempts after that show no errors. Only errors right after I switch .exe files from older to newer.

Looks like this script is emulating a browser request. You probably already know this but just for the sake of clarity, this problem is most dominant when the script acts like a server and is trying to satisfy the client browser's request. When the request is satisfied the client normally closes the socket. This is where @error -1 was super handy in older versions of TCPRecv, allowing the server to acknowledge the closed socket on it's own end.

Newer versions of TCPRecv seem to be vastly compromised because of the new @error levels.
Also TCPStartup() never ever shuts down unless the server is deactivated (in my script). It looked like the repo script was constantly starting and stopping. (Don't know if that matters)

comment:17 Changed 4 years ago by Jpm

The repro script was the one posted in the forum, no change in the logic.
THe intend version does not intend to change any of previous except implemenation of the TCPConnect timeout.
I am not a specialist of this net function. so please an update of the last post repro script so I can understand what should help. Perhaps you need 2 script one for the server and the other for the client.
Thanks for your cooperation

comment:18 follow-up: Changed 4 years ago by diegomainster@…

Hello, I created this ticket, once I started ignoring @error = -1, my server is running fine, I'm using version 3.3.10.2, created these 2 scripts to demonstrate how do I detect when the client or server closes the connection, it works for me:

Server: http://pastebin.com/JPf3A8KE
Client: http://pastebin.com/irVGLpde

comment:19 Changed 4 years ago by Jpm

Many thanks,
Now I understand better (I think ?)
If the connection is closed by the other side you received in 3.3.8.1 -1
now with my TCPConnect implementation you received 10054 which means connection reset by peer which is better as the @error less than 0 can set in other situation

I Think you can agree that my TCPConnect() timeout solution is working fine as 3.3.8.1

Cheers
Jpm

comment:20 in reply to: ↑ 18 Changed 4 years ago by anonymous

Replying to diegomainster@…:

Hello, I created this ticket, once I started ignoring @error = -1, my server is running fine, I'm using version 3.3.10.2, created these 2 scripts to demonstrate how do I detect when the client or server closes the connection, it works for me:

Server: http://pastebin.com/JPf3A8KE
Client: http://pastebin.com/irVGLpde

Thank you for the examples. I'm glad that is working for you.
This does not work for what i'm doing. The only difference I can tell here is that i'm not using a Autoit3 client side version to connect to the server. (Don't know why that matters.) Same problem, Autoit3 server can't tell when client web browser closes the socket where older versions could.

I'm trying to get an example script working that will show case exactly what is happening between version 3.3.8.1 and the newer version 3.3.10.2 that will hopefully not make things even more confusing.

This is what i have learned so far.
Autoit3 v3.3.8.1 installed by using the setup download. Works as expected...
Autoit3 v3.3.10.2 installed by using the setup download. @error -1 is different, and causes problems when detecting a web browser closed socket. > 0 @error does not help here for whatever reason. Installing the beta version.exe did not seem to help.

HOWEVER.
When using the beta version on 3.3.8.1 there does not seem to be the problem that genuine 3.3.10.2 installs seem to have.(This was very confusing to me when making the trouble shooting script because I was assuming that it would not work.)

So unless you know a better way then I would recommend using the setup installers for switching between autoit3 versions. Uninstall-reinstall between 3.3.8.1 and 3.3.10.2 and then run the bellow repro script.

HOWEVER!
This too cause me problems! But I do not want to get into detail about it other than to warn you that when I was installing between versions that version 3.3.8.1 was acting out of character and I had to download a fresh copy of the 3.3.8.1 to correct it.
(Was getting extra TCP connections to the server that sent no data but would eventually close)

Before I was just swapping out exe files between beta and 3.3.8.1 when making this script, but the problem does not seem to start until you install the genuine 3.3.10.2 and then try swapping out with the beta version.

comment:21 Changed 4 years ago by anonymous

Sorry it is not working fine, I have tested all day and it is still not as good as old versions...

comment:22 Changed 4 years ago by anonymous

Would you like to see my repro script?

comment:23 Changed 4 years ago by FixTCPRecvForNewVersions

Sorry I was afraid you were going to close the ticket before I could finsih...
Here is the reproduction script.

Well here it is, hope it helps.
Remember the only way to reproduce the error that I know of is two use un-install and re-install between 3.3.8.1 and 3.3.10.2

This also creates a junk file to quickly simulate outgoing requests.
Hope that is ok.


#include <File.au3>
$fletemp = _TempFile(@WorkingDir & "\","JUNK",".ini")

$listsck = ""
$lstnhst = "127.0.0.1"
$lstnprt = 81
$maxrecv = 1000
$maxpend = 10
$version = @AutoItVersion
$warning = "Begin this test by pointing your web browser to the host address." & @CRLF & "Host ip: " & $lstnhst & ":" & $lstnprt & @CRLF & @CRLF
If $version <> "3.3.8.1" Then $warning &= "TCPRecv might not detect client side closed sockets, try version 3.3.8.1 for a working example."
MsgBox(0,"Autoit3 Version?",$warning & @CRLF & "You are using AutoIt3; " & $version)
$srvrnme = "TESTING TCPRecv v" & $version
$srvrmsg = $srvrnme
If $version = "3.3.8.1" Then
	$srvrmsg &= " (Can easily detect client side closed sockets)"
Else
	$srvrmsg &= " (May not detect client side closed sockets very easily if at all, try version 3.3.8.1)"
EndIf


TCPStartup()
If @error Then
	MsgBox(0,$srvrnme,"TCPStartup ERROR: " & @error)
	quit()
Else
	$srvrsck = TCPListen($lstnhst,$lstnprt,$maxpend)
	If @error Then
		MsgBox(0,$srvrnme,"TCPListen ERROR: " & @error)
		quit()
	Else
		MsgBox(0,$srvrnme,$srvrsck)
	EndIf
EndIf

$blankexample = False
$loop = 0
While 1
	$clntsck = TCPAccept($srvrsck)
	If @error Then
		MsgBox(0,$srvrnme,$srvrsck & " TCPAccept ERROR: " & @error)
		quit()
	ElseIf $clntsck <> -1 Then
		$listsck &= $clntsck & "_"
	EndIf
	$split = StringSplit($listsck,"_")
	For $x = 1 To $split[0]
		If $split[$x] <> "" Then
			$clntsck = $split[$x]
			$clntmsg = TCPRecv($clntsck,$maxrecv)
			$ierror = @error
			If $ierror Then
				If $version <> "3.3.8.1" Then
					MsgBox(0,$srvrnme,"Socket: " & $clntsck & " Client message??? (" & $clntmsg & ")" & @CRLF & @CRLF & "Error??? " & $ierror)
					If $blankexample = True Then
						TCPCloseSocket($clntsck)
						IniDelete($fletemp,"SOCKETRQST",$split[$x])
						$split[$x] = ""
					EndIf
				Else
					MsgBox(0,$srvrnme,"Socket: " & $clntsck & " TCPRecv has detected the client side closed socket and will now close the local socket. @error " & $ierror & @CRLF & @CRLF & $clntmsg)
					If $blankexample = True Then
						TCPCloseSocket($clntsck)
						IniDelete($fletemp,"SOCKETRQST",$split[$x])
						$split[$x] = ""
					EndIf
				EndIf
			ElseIf $clntmsg <> "" Then
				IniWrite($fletemp,"SOCKETRQST",$clntsck,"Fake Message")
			Else
				$test = "set error for blank returns!? BBADD!"
				If $version = "3.3.8.1" Then $test = "error not set! GOOD!"
				MsgBox(0,$srvrnme,$blankexample & " Blank return detected, " & $ierror & @CRLF & @CRLF & $test & @CRLF & @CRLF & $clntsck)
				$blankexample = True
			EndIf
		EndIf
	Next
	If $listsck <> "" Then
		$listsck = ""
		For $x = 1 To $split[0]
			If $split[$x] <> "" Then
				$clntsck = $split[$x]
				$listsck &= $clntsck & "_"
				$clntmsg = IniRead($fletemp,"SOCKETRQST",$clntsck,"")
				If $clntmsg <> "" And $blankexample = True Then respond()
			EndIf
		Next
	EndIf
	Sleep(100)
	$loop += 1
	If $loop >= 500 Then quit()
WEnd


Func respond()
	$size = StringLen($srvrmsg)
	$header = "HTTP/1.0 200 OK" & @CRLF
	$header &= "Content-Length: " & $size & @CRLF
	$srvrsnd = $header & @CRLF & $srvrmsg
	If $blankexample = True Then TCPSend($clntsck,$srvrsnd) ; Stop respond to better show the error example.
	If @error Then
		MsgBox(0,$srvrnme,"TCPSend: " & @error)
		quit()
	Else
		MsgBox(0,$srvrnme,"Client reqested: " & @CRLF & @CRLF & $clntmsg & @CRLF & @CRLF & "Message was sent to client: " & $clntsck & @CRLF & @CRLF & $srvrsnd)
		If $version <> "3.3.8.1" Then
			$theproblem = "This version must force close the connection here since @error -1 no longer behaves as expected.  But going to leave it open for example." & @CRLF
			$theproblem &= "Force closing connections can have harmless but un-desirable effects for the client." & @CRLF
			$theproblem &= "@error -1 will be set for blank returns, which compramises the ability to detect client side closed sockets."
			MsgBox(0,$srvrnme,$theproblem)
		EndIf
	EndIf
EndFunc



Func quit()
	TCPShutdown()
	FileDelete($fletemp)
	Exit
EndFunc












comment:24 Changed 4 years ago by FixTCPRecvForNewVersions

Sorry for junking things up, just wanted to let it be known that the extra TCP connections were obviously something my browser was doing and was able to fix it by turning off a setting. (Just never seen that before and was confusing me)... That issue has nothing to do with autoit3 and i'm sorry for bringing that up.

If you need more insight on the @error for new versions then i'd have to make a video of exactly what i'm experiencing over here to show you, if the new repro script does not help at all.

Thanks for your time.

comment:25 Changed 4 years ago by FixTCPRecvForNewVersionsPLEASE

Ran tests on a different operating system and it confirmed that TCPRcv still can not detect a client side closed web browser socket as older versions did. I tried the @error > 0 solution and still was unable to detect the client side closed web browser socket via @error 10054. Socket stays open forever even when the browser is closed.

Something is off there and it is killing autoit3's ability to function efficiently as a web server. Even worse try mixing the two together as a script that can do web serving and accept persistent autoit3 client connections. Can be done but 3.3.8.1. will out speed any newer version scripts at the same time be more reliable.

If you wish to continue thinking there is nothing wrong with TCPRecv then fine i'm ok with that. Future autoit3 users should be aware that scripting a web server with the newer versions wont be as effective. 3.3.8.1 will dominate over newer scripts with speed and rely ability. You might as well retire any thought of having a descent web servers using autoit3 for here on out if the issue is not resolved.

Good luck.

comment:26 Changed 4 years ago by diegomainster@…

I created a video to demonstrate it on my web server when the browser closes the connection, the connection is closed, don't "stays open forever":

https://www.youtube.com/watch?v=_s0KJGPtXgw

comment:27 Changed 4 years ago by anonymous

I've done everything I know of to try and make your solution work without any success at all. I've tested it on three different operating systems and still nothing. I'm very confused at this point why @error > 0 will work for you when I can't even get a received message most of the time using that. Guess i'm SOL. If you have any last suggestions or ideas on what I need to fix in the reproduction script then please share them. I don't want to be stuck on 3.3.8.1 forever and am very curious as to what i'm doing differently that it will work for you and not me.

I've tried everything I can think of and am ready to concede the subject and just live with what I've got.

Thanks.

comment:28 Changed 4 years ago by anonymous

Sorry miss spoke again. I can receive the message, just can't detect the @error > 0 in order to close the socket.

Sorry for wasting your time.

comment:29 Changed 4 years ago by anonymous

Sorry miss spoke again. I can receive the message, just can't detect the @error > 0 in order to close the socket.

Sorry for wasting your time.

comment:30 Changed 4 years ago by anonymous

Sorry but this is driving me NUTS!
I'm sorry for spamming your forum.

If there is no TCPRecv error then why the holy molly is it so hard to work with now?
Why in gods name is this not working????
When diegomainster example server/client scripts can detect the error without a problem?

I concede that it is probably my scripting but what the heck happened that made TCPRecv so hard to deal with now?!? What in the world am I doing wrong? If you can explain this to me that would be great, in the meantime i'll search for a new place to research this.

When I run this script and open a web browser and goto the address and then close the browser the script does not detect @error > 0 !!!

Please explain to me if TCPRecv is not bugged, what in the WORLD am I doing wrong here?

TCPStartup()
$serversock = TCPListen('127.0.0.1',81)
While 1
	Do
		$hi = TCPAccept($serversock)
	Until $hi <> -1
	MsgBox(0,"Connected","A client has connected...")
	While 1
		TCPRecv($hi,1500)
		If @error > 0 Then
			MsgBox(0,"Closed","Closing the connection: " & @error)
			TCPCloseSocket($hi)
			ExitLoop
		EndIf
	WEnd
WEnd

comment:31 follow-up: Changed 4 years ago by diegomainster@…

Now I understand the problem you described, and me using your code also happened in version 3.3.8.1. I realized that if you call TCPSend() sometimes, TCPRecv() detects the closing of the connection, as in the code below:

TCPStartup()
$serversock = TCPListen('127.0.0.1', 81)
While 1
	Do
		$hi = TCPAccept($serversock)
	Until $hi <> -1
	MsgBox(0,"Connected","A client has connected...")

	$ti = TimerInit()

	While 1
		TCPRecv($hi,1500)
		If @error > 0 Then
			MsgBox(0,"Closed","Closing the connection: " & @error)
			TCPCloseSocket($hi)
			ExitLoop
		EndIf

		If TimerDiff($ti) > 99 Then
			TCPSend($hi, 'data')
			$ti = TimerInit()
		EndIf

	WEnd
WEnd

So, there is even a problem with TCP in autoit.

comment:32 in reply to: ↑ 31 Changed 4 years ago by anonymous

Replying to diegomainster@…:

Now I understand the problem you described, and me using your code also happened in version 3.3.8.1.

I also tested the scripts with both versions. And 3.3.8.1 did not reflect the same problems as newer versions. I will assume that when you ran your scripts that @error was still set to > 0. (Easy miscalculation to do and would not hold it against a master coder like you or anyone else to oversee, I have done it countless times) But I realize assumptions are often misleading and am willing to diagnose why my version of 3.3.8.1 worked when @errror level is set properly for the version that is installed, when yours did not.

3.3.8.1 requires @error of any kind in order to close the socket.(Wow that is easy!)

Later versions seem to require an error > 0... Or oven perhaps less than -1...
definitely not an @error of -1 whatever you do. (@error -1 is worthless, and same as blank, why do we need two?)

Later version also seem to require some kind of delay witch TCPRecv never ever ever needed before. TimerInit seems to be the main root of why my scripts fail and your scripts succeed.(Best guess so far)

Bottom line:
Version 3.3.8.1 - When I tested did not require a TCPsend nor TimirInit delay, in oder to close the socket.
Later versions - Seem to require TimirInit before a response/closing. (Which is confusing but i'm ok with as long as there is proper documentation on how to implement the function because Autoit3 is great and should be available to use for everyone, not just elites. And that is what they have done to the best of their ability so far, and I'd hate to say that TCPRecv is not user friendly when it is possibly the most common used function of all time)

Once again I appreciate your patients in dealing with a guy like me who is a newbie to forums and coding, Autoit3 has been good to me for a long time and it upsets me that something I have been using for years no longer works the way I expected.

Now come on lets be honest please, which would you prefer... 3.3.8.1 needs no further action other than @error -1 to close a socket...

Later versions require a time delay, plus you got to ignore @error -1 because it is...??? uhh... Blank i guess, same as the return value? -1 = "" ok.... @error > 0 close socket... Oh plus developers got to make new example scripts to help newbies to learn. (Not that hard, but wow, 3.3.8.1 TCPRecv was so much more user friendlier)

You tell me which is not going to confuse the heck out of somebody who is learning TCPRecv.

3.3.8.1 @error -1 CLOSE THE SOCKET (DONE)
3.3.10.2 @error > 0 CLOSE THE SOCKET (OOOPS you forgot the time delay! TRY AGAIN!!!)

Not trying to be disrespectful just trying to make a point.
Sorry for the offence if any.

My overall goal is to help Autoit3 be the best it can be, and they probably are doing a great job without me, but the TCPRecv is my lively hood and means a lot to me. I have no problem staying with 3.3.8.1 for the rest of my days if that is all I can get to work for TCPRecv heavy scripts.

Thank you for your time.

I still love Autoit3, and they still deserve all the donations they can and will get.

comment:33 Changed 4 years ago by anonymous

In 3.3.8.1 it is even simpler than i describe it.. All you need is an @error of any kind to close the client side socket.

Newer versions require you to ignore @error -1 plus do a timer init delay before sending data. (If I understand correctly)

comment:34 Changed 4 years ago by anonymous

For the sake of clarity, this is a working example of 3.3.8.1 with proper @error detection set for the installation of genuine Autoit3 v3.3.8.1 and modified to remove server response to lesson the confusion.

When executed with 3.3.8.1 the script will close the socket as expected.
When executed with any other script greater than this version problems may arise!

Newer version require the comments to be removed, and @error detection be > 0...
And I believe without any further testing that this is the root difference between diegomainster's working examples and my failing examples.(Not tested elsewhere except the recent reproduction scripts).

Thank you all for helping me understand the new TCPRecv function.
Still don't care to add TimerInit, i'll stay with 3.3.8.1 for TCP related scripts until it is more user friendly(if ever).

Please update the example 'help' scripts for TCPRecv to reflect these changes if you had not already, or aren't planing to do so. (They are amazing and taught me everything I know, thank you for that)

TCPStartup()
$serversock = TCPListen('127.0.0.1', 81)
If @error Then Exit ; we know this one.
While 1TCPRecv

Do

$hi = TCPAccept($serversock)
If @error Then Exit ; we know this one.

Until $hi <> -1
MsgBox(0,"Connected","A client has connected...")

$ti = TimerInit()

While 1

TCPRecv($hi,1500)
If @error Then

MsgBox(0,"Closed","Closing the connection: " & @error)
TCPCloseSocket($hi)
ExitLoop

EndIf

#cs
If TimerDiff($ti) > 99 Then

TCPSend($hi, 'data')
If @error Then MsgBox(0,"SEND ERROR!",@error)
$ti = TimerInit()

EndIf
#ce

WEnd

WEnd

comment:35 Changed 4 years ago by anonymous

Whoops sorry, that one before this one got messed up somehow... This one should do better.

TCPStartup()
$serversock = TCPListen('127.0.0.1', 81)
If @error Then Exit ; we know this one.
While 1
	Do
		$hi = TCPAccept($serversock)
		If @error Then Exit ; we know this one.
	Until $hi <> -1
	MsgBox(0,"Connected","A client has connected...")

	$ti = TimerInit()

	While 1
		TCPRecv($hi,1500)
		If @error Then
			MsgBox(0,"Closed","Closing the connection: " & @error)
			TCPCloseSocket($hi)
			ExitLoop
		EndIf

		#cs
		If TimerDiff($ti) > 99 Then
			TCPSend($hi, 'data')
			If @error Then MsgBox(0,"SEND ERROR!",@error)
			$ti = TimerInit()
		EndIf
		#ce
	WEnd
WEnd

comment:36 Changed 4 years ago by Jpm

Can you switch the discussion to Forum as too may post for a track report.

For me the uploaded version for solving the TCPConnect timeout and clarification of @error is enough to have a good handling of peer disconnection as @error is set to 10054 which exactly what MSDN is describing

WSAECONNRESET = 10054

Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

Last edited 4 years ago by Jpm (previous) (diff)

comment:37 Changed 4 years ago by anonymous

Too bad that don't work for connected WEB BROWSER clients. 3.3.10.2 STILL can't detect 10054 and MUST rely on other means to detect the error when a client connects to the server with a WEB BROWSER! Even then the error is 10053 (PROTOCOL ERROR) and not a TIMEOUT because the socket is long closed on client side before any kind of time out (On client side) can occur.

I say it again! 3.3.10.2 CAN NOT detect 10054 when a web browser like CHROME OR anything else connects to the server...

The last two above scripts are the PROOF of it...! (comment 30 31 should be enough to proof that 3.3.10.2 TCPRecv @error detection is BROKEN when detecting client side closed browser sockets where 3.3.8.1 had no problems what soever!)

Thank you for your time.

comment:38 Changed 4 years ago by Jpm

I agrre that my TCPConnect timeout solution must be committed I will speak with Jon which is the only one which can commit for AutoIt change

comment:39 Changed 4 years ago by Autoit3 is Awesome!

Thank you for taking the time to investigate the matter. I appreciate the Autoit3 team's hard work and you guys/gals are doing an amazing job!

Thanks again.

comment:40 follow-up: Changed 4 years ago by Lbsl

I stumbled upon the same problem.
Also evaded it by ignoring errors < 0.
But somehow this still does not solve the performance issue with tcprecv.
It seems to me that the Tcprecv is not clearing its buffers when it transferred the data content to my own receive buffer variable.

I have been running a simple client and server app that is parsing an enormous log-file from one side to the other.
It seems to choke faster the smaller the receive buffer size i set.
If i set it to receive 10.000 characters, the flow streams efficiently a lot longer yet eventually chokes as well (making the flow stutter), but if i set the receive buffer to 1K, it seems to choke much faster.

Whatever AutoIT 3.3.8.1 did on the TCPRecv and Send functions, worked much more efficiently than it currently does in the 3.3.10.2

Cheers.

comment:41 in reply to: ↑ 40 Changed 4 years ago by Lbsl

Replying to Lbsl:

Whatever AutoIT 3.3.8.1 did on the TCPRecv and Send functions, worked much more efficiently than it currently does in the 3.3.10.2

I overread the TCPTimeout comments above:
I figured out that the TCPTimeout (which is set to 500msecs in my case) is executed also on the errors below 0. I don't think this is really necessary as these errors are certain not to resolve the stuff that the -x errors produce, without developer intervention.
For sure the timeout should not be applied when the TCPRecv error is -1.

comment:43 Changed 3 years ago by anonymous

That don't answer anything about how jacked up the new TCPREcv is...

comment:44 Changed 3 years ago by Jon

  • Milestone set to 3.3.13.2
  • Owner set to Jon
  • Resolution set to Fixed
  • Status changed from new to closed

Fixed by revision [10303] in version: 3.3.13.2

comment:45 Changed 3 years ago by TCPRecvFix

Tested a script with AutoIt version 3.3.13.16 beta and though TCP error detection has been improved it still can not detect client side closed sockets as 3.3.8.1 is able to do. The fixed version still requires a timeout to close the client side socket when dealing with a web browser. I love that empty returns do not set @error anymore, but it's still depressing that @error is not set for a client side web browser connection termination.

I don't know if this is a bug any more or a design change, so I wish to make a request as a big fan of AutoIt3 that you seriously consider 3.3.8.1's ability to detect client side web browser connection terminations and implement that in future versions.
I have created a script that can demonstrate this ability if your interested in pursuing this any further.

Thanks for taking the time to improve TCPRecv, and i'll do my best to adjust to the alternate methods for closing sockets.

comment:46 Changed 20 months ago by internetmonkeyboy@…

As of today still not setting @error level. Why is this still broken?

comment:47 Changed 20 months ago by internetmonkeyboy@…

Local $shost = "www.google.com"
Local $sPage = "/"
Local $iPort = 80

TCPStartup()

Local $sName_To_IP = TCPNameToIP($shost)

Local $iSocket = TCPConnect($sName_To_IP, $iPort)
If $iSocket = -1 Then

TCPCloseSocket($iSocket)
MsgBox(0, "Socket Connect Error", $iSocket, 0)
Exit

Else

MsgBox(0, "Socket Connected", $iSocket, 1)

EndIf

Local $sCommand = "GET " & $sPage & " HTTP/1.1" & @CRLF

$sCommand &= "Host: " & $shost & @CRLF
$sCommand &= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0" & @CRLF
$sCommand &= "Referer: " & $shost & @CRLF
$sCommand &= "Connection: close" & @CRLF & @CRLF

Local $BytesSent = TCPSend($iSocket, $sCommand)
If $BytesSent = 0 Then

MsgBox(0, "Sending Error", $BytesSent, 0)
Exit

EndIf

Local $sRecv = ""
Local $sCurrentRecv ;= ""

While 1

$sCurrentRecv = TCPRecv($iSocket, 1000)
If @error <> 0 Then ExitLoop
MsgBox(0, @error, $sCurrentRecv, 1)

WEnd

TCPCloseSocket($iSocket)
TCPShutdown()

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain Jon.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.