Jump to content

TCPRecv and v3.3.12.0


Recommended Posts

Okay, here's another stab and is up for review.

I made it as an include this time, so you can test it in your scripts without

doing too many modifications and to test the error returns.

Just #include this script and replace TCPRecv with _WSA_TCPRecv and you're good

to go.

I downloaded a 1.2GB file with it today and it was also tested for server

disconnects with no problems.

Please review the code to find out what to expect from this script.

jpm,

I think I figured out what the problem is with disconnect -2.

There's a mention of it in the script below.

There are 3 possible returns from "recv".

1. blank = no bytes received.

2. 0 = disconnected.

3. greater than 0 = bytes received.

attachicon.gif_WSA_TCPRecv.au3

Thanks goes to ProgAndy and JScript -- I borrowed some of their code.

The non-blocking code by ProgAndy, was obtained from here:

'?do=embed' frameborder='0' data-embedContent>>

I don't understand how an int can be blank

Link to comment
Share on other sites

jpm,

That IS exactly how it is.

I've learned over the years to never take MSDN as absolute.

Especially when they name example usage as LEAN AND MEAN.

It's like pulling teeth to get a peek at the light for all the darkness.

"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

jpm,

That IS exactly how it is.

I've learned over the years to never take MSDN as absolute.

Especially when they name example usage as LEAN AND MEAN.

It's like pulling teeth to get a peek at the light for all the darkness.

whoah ...

I will check again the proposed AutoIt code with what you suggest

Stay tune

THanks

Link to comment
Share on other sites

In the code that ProgAndy used in _TCPConnect(), a non-blocking socket is used

to set a timeout for a connection, and then set to blocking again once the

connection is established. I'm not really sure what the proper protocols are

between the two. I can't seem to find any documentation that suggest how

they should be used, or even under what circumstances.

TCPConnect() may use non-blocking to connect, but it seems that a dll call

using "recv" is in blocking mode under normal conditions. At least that

was my experience when I first tested it.

Since I'm not privy to that code in AutoIt, I can only guess. But when I use

a dll call using "recv" from TCPConnect(), it is in blocking mode, until a

non-blocking call is issued.

With that said, I can use ProgAndy's _TCPConnect(), and comment the blocking

call towards the end of the script, and the dll "recv" call is non-blocking,

and works accordingly.

You don't have to change anything with that in regards to the AutoIt code anyways.

The main reason for this last script was to show what the "recv" returns were,

so that it might be helpful with the disconnect -2 problem.

So, if you were to implement those returns, somewhat like the script suggest,

then I think that problem will be fixed.

"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

My upload test of AutoIT3.exe is using the exact @progandy code,

so my concern is to understand if such use of non-blocking socket can be used in other place at least in TCPRecv as you suggest without bringing some regression.

Link to comment
Share on other sites

My upload test of AutoIT3.exe is using the exact @progandy code,

so my concern is to understand if such use of non-blocking socket can be used in other place at least in TCPRecv as you suggest without bringing some regression.

Well now, that presents a puzzle.

How is TCPRecv in non-blocking mode?

If TCPRecv was in blocking mode, then it would "wait" indefinitely for

incoming data, unless some type of timeout was issued, like 10ms.

Which, I don't think you can issue a timeout while in blocking mode.

Hence, the ProgAndy code.

Perhaps there is more code in one of the libraries that deals with it.

In any case, the answer to your question is, I didn't experience any

noticeable difference or problems while using it.

If you adapt ProgAndy's _TCPConnect(), then you might have no choice

but to use the script I posted at #40. Because that is exactly what

I wound up having to do. I had no choice, if I wanted it to work

properly.

---

As a side matter, I worked with a blocking function that I named:

_WSA_TCPRecvWait(). The idea was to wait for 3 seconds and if no

data received then return. I couldn't get it to work in that mode.

Somehow TCPRecv is in non-blocking mode when called. If not in your

code, then in one of the includes. Or perhaps it is called differently

than in the script. I don't know - I'm in the dark at this point, again.

"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

As a side matter, I worked with a blocking function that I named:

_WSA_TCPRecvWait(). The idea was to wait for 3 seconds and if no

data received then return. I couldn't get it to work in that mode.

You have to use a non-blocking socket and the function select() to do this.

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

@funkey

I figured that way, then that means that all the socket should have a single mode of operation?

I find most interesting is the TCPSend it were in non-blocking mode

JS

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

You have to use a non-blocking socket and the function select() to do this.

Thanks, but I'm aware of that. Did you review the script at post #40?

By the way funkey, since you are familiar with WSA sockets, you should be

giving your points of view. It's good to hear from you anytime!

Do you have any knowledge on blocking and non-blocking protocols?

When they should or should not be used? What are the pros and cons?

What are the security concerns? I'm looking for documentation.

I think I have an idea to run them more efficiently.

Edited 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

@funkey

I figured that way, then that means that all the socket should have a single mode of operation?

I find most interesting is the TCPSend it were in non-blocking mode

JS

I think TCPSend can be set in non-blocking mode, but I'm not sure at

this point, what effects it will have. I will have to play with it

sometime within the next week.

Let's get TCPRecv working properly first.

-edit- silly editor

Edited 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

Please review - final stab - I hope.

Included is:

_TCPConnect() - a rewrite of the original code.

_WSA_TCPRecv() - removed the blocking calls and modified a few lines.

_TPCRecv_Example() - example usage for a function.

- edit- code deleted to avoid confusion.

Edited 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

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

I always test if there is data availabe with select(). I don't understand the documentation because of the maxlen parameter. It it the buffer size for recv or is it to cut of the result?
Here is what I made but I did not enough testing:

#include "socket_UDF.au3"


Global $sIP = "www.google.com"
Global $iPort = 80
Global $ConnectionTimeout = 1500

Global $tReadFds = DllStructCreate($tagFd_set)
Global $tReadFds_Copy = DllStructCreate($tagFd_set)


_WSAStartup()

Global $iSocket = _TCPConnect($sIP, $iPort, $ConnectionTimeout)
If @error Then
    ConsoleWrite("_TCPConnect() error " & @error & " / (" & @extended & ") connecting to " & $sIP & ":" & $iPort & @LF)
    _WSACleanup()
    Exit
EndIf
ConsoleWrite("Connection established to " & $sIP & ":" & $iPort & @LF)
ConsoleWrite("New socket: " & $iSocket & @LF & @LF)

TCPSend($iSocket, "GET /index.html HTTP/1.0" & @CRLF & @CRLF)

Global $sHTML = _TCPRecv($iSocket)
If @error Then
    ConsoleWrite("_TCPRecv() error " & @error & " / (" & @extended & ") for socket " & $iSocket & @LF & @LF)
EndIf

_closesocket($iSocket)

_WSACleanup()

ConsoleWrite($sHTML & @LF)


Func _TCPRecv($iSocket, $iBufLen = 2048, $iTimeout = 2000)
    Local $iRetSelect, $iRetRecv;, $sRet = "", $sTemp = ""
    Local $tReadFds = DllStructCreate($tagFd_set)
    Local $tReadFds_Copy = DllStructCreate($tagFd_set)
    Local $tBuffer = DllStructCreate("char buffer[" & $iBufLen & "]")

    _FD_ZERO($tReadFds)
    _FD_SET($iSocket, $tReadFds)

    While 1
        DllCall('ntdll.dll', 'none', 'RtlMoveMemory', 'struct*', $tReadFds_Copy, 'struct*', $tReadFds, 'ULONG_PTR', DllStructGetSize($tReadFds))
        $iRetSelect = _select($tReadFds_Copy, $iTimeout)
        Switch $iRetSelect
            Case $SOCKET_ERROR
                Return SetError(1, _WSAGetLastError(), "")
            Case 0 ; Timeout (no or no more data)
                Return SetExtended(0, "")
            Case Else
                If _FD_ISSET($iSocket, $tReadFds_Copy) Then
                    DllCall('ntdll.dll', 'none', 'RtlZeroMemory', 'struct*', $tBuffer, 'ULONG_PTR', DllStructGetSize($tBuffer))
                    $iRetRecv = _recv($iSocket, $tBuffer)
                    Switch $iRetRecv
                        Case $SOCKET_ERROR
                            Return SetError(2, _WSAGetLastError(), "")
                        Case 0 ; Connection closed or no more data
                            Return SetError(3, 0, "")
                        Case Else
                            Return SetExtended($iRetRecv, DllStructGetData($tBuffer, 1))
                    EndSwitch
                Else
                    ExitLoop
                EndIf

        EndSwitch
    WEnd
EndFunc   ;==>_TCPRecv
Edited by funkey

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

Just my opinion, but I think TCPConnect should be left in

non-blocking mode in AutoIt. Blocking mode may have its

applications - but this is not one of them.

-edit-

I changed my mind on the statement above when I found out

the security concerns on non-blocking sockets.

------

And there is no point in switching between the two.

So here is how it works, based on observation:

1. The default state of a socket is in blocking mode.

It works just like "any blocking function".

2. The dll call to "ioctlsocket", last parameter "1",

changes it to non-blocking mode. In my script, using

_TCPConnect(), it is left in non-blocking mode, until

the socket is closed.

3. The behavior of non-blocking mode works as it should.

MS added a 10035 non-fatal error while in that mode.

It is basically saying, that the non-blocking socket

has no data queued (or it's blank), so try again!

That behavior, is what we expect from TCPRecv.

4. There is no noticeable difference when using TCPSend

at this point. It works like it always has.

5. There are two new features, if added to AutoIt:

- TCPConnect would have a timeout option/parameter.

For instance 3 seconds, instead of the default 20 seconds,

which that has never been acceptable.

- TCPRecv would return "bytes received" in @extended.

This will save coders from all those StringLen() calls.

It's in the dll call, might as well put it to good use!

@extended returns:

0 = no bytes received.

>0 = number of bytes received.

---

Hmm, I can't think of anything else right now.

I have things to do - maybe later.

Edited 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

I always test if there is data availabe with select().

Could you post the dll call using "select" to test availability?

DllCall(...)

I don't understand the documentation because of the maxlen parameter.

It it the buffer size for recv or is it to cut of the result?

It's the buffer size. (the number of bytes to receive)

When you set the buffer size, "recv" will fill data up to that size.

Hence, maxlen.

"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

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...