AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Client & Server Script for TCP/IP Network Communication
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
qtmspin



Joined: 17 Oct 2006
Posts: 23

PostPosted: Thu Dec 28, 2006 3:57 am    Post subject: Im stuck... Reply with quote

I've run into a limitation and annoying 'bug' It seems if I send messages too fast, ie in a loop like the one below... only the first two get to the client, the other 3 are lost in cyberspace...

If I put a pause of 200 ms in the server code all 5 are delivered to the client. I've tried changing the "ReceivedDataSize = 4096" to both higher and smaller numbers, but nothing has worked.

server code:
Code:

Loop, 5 {
   SendText=test message,%A_Index%
   GoSub SendViaNet
}


200 ms is no good, is there another way to send these messages and be sure they will arrive?

Thanks in advance. I've done so much using this script that never would have been possible without it.

Matt
Back to top
View user's profile Send private message
Zed Gecko



Joined: 23 Sep 2006
Posts: 149

PostPosted: Fri Dec 29, 2006 4:01 am    Post subject: Reply with quote

Well iīve had no time-critical tasks for this script right now,
so iīm wildly guessing here.

First i would suppose, that you set the scripts speed at maximum with
Code:

SetBatchLines -1


If this doesnīt help, youīll have to find out if itīs the sending part or
the receiving part that looses the data.
You could connect the sender to a Telnet-Client (like Hyperterminal)
and see if the data is send out properly.

If it does send all the data properly,
it could help to get rid of OnMessage and
call the ReceiveData function in an endless loop.

If the sender already looses the data,
there is probably no easy solution.

BTW: I donīt think changing the ReceivedDataSize will be necessary,
i can receive large html-files with the script without problem.
Back to top
View user's profile Send private message
qtmspin



Joined: 17 Oct 2006
Posts: 23

PostPosted: Fri Dec 29, 2006 6:24 am    Post subject: Reply with quote

It's definatetly the receiving part (my client). I did like you said and hooked up telnet, wow that was easy and cool too! The server is sending everything, however the client is only getting the first two lines.

I already used, Setbatchline -1
I've also got the priority set to realtime
I tried using a loop like this:

Code:
SetTimer, ReceiveDataSub, 0, 1

ReceiveDataSub:
   Thread, Priority, 1
   receiveData(socket, 0)
Return

I still have to slow down the sending inorder to get the data.... back to the drawing board. Thank you for your suggestions.
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6836
Location: France (near Paris)

PostPosted: Fri Dec 29, 2006 9:41 am    Post subject: Reply with quote

Well, you use a scripting language, it is not as fast as a native C program, so you must live with its limitations (speed, memory use, etc.).
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
qtmspin



Joined: 17 Oct 2006
Posts: 23

PostPosted: Sat Dec 30, 2006 12:16 am    Post subject: Is telnet accurate? Reply with quote

I've noticed that when I hook telnet up to the server I get different data then what seems to be delivered to my client.

I tested it out w/ Zed's original script and I get the same thing. Here is what happens...

If I send the text 123456 from the server, 123456 arrives at the client (telnet terminal)

However if I send a shorter string next ie (1234)

123456 arrives at the client (telnet)

I am wondering if the 'pipe' is not being emptied, or perhaps this is a telnet buffer issue?
Back to top
View user's profile Send private message
Zed Gecko



Joined: 23 Sep 2006
Posts: 149

PostPosted: Sat Dec 30, 2006 5:17 am    Post subject: Reply with quote

Well,
you have probably reached the limits of this language here.
As i can see from the code you have send me,
your ReceiveData function is quite long, and even includes
some MsgBoxes.
So i suppose the buffer of the socket gets filled up while your function
is running.
It would maybe help to make the ReceiveData function just add the received data to a var
and let another (timed) subroutine work with the
data from this var.
But this could produce a lot of new problems, and iīm not shure, if it
would really reduce the "round trip time".

There might be a way to increase the buffer of the socket with the
DLLCall of setsockopt with the value SO_RCVBUF:
http://msdn2.microsoft.com/en-us/library/ms740476.aspx
but i donīt know how to handle it.

The MSDN gives some general hints on speeding up network applications:
http://msdn2.microsoft.com/en-us/library/ms738559.aspx

But the safest way would be probably multithreading, which is not really
possible in AHK (we would need something like #MaxThreadsPerHotkey for OnMessage functions).
Back to top
View user's profile Send private message
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 6:15 am    Post subject: Re: Im stuck... Reply with quote

qtmspin wrote:
I've run into a limitation and annoying 'bug' It seems if I send messages too fast, ie in a loop like the one below... only the first two get to the client, the other 3 are lost in cyberspace...
<snip>
200 ms is no good, is there another way to send these messages and be sure they will arrive?


The TCP protocol assures delivery so yes, you can. It's been years since I've done network programming so I'm not much use for providing an answer, but I'm guessing an error status isn't being checked on one of the calls, and based on what info you've provided, it's probably related to the server's send. Perhaps the network buffer is filling up and the later send's are really failing?

Unlike UDP, the TCP protocol assures delivery or a failed status when transmission is unsuccessful. There's a mistake in the code somewhere.
Back to top
View user's profile Send private message
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 6:56 am    Post subject: Reply with quote

Ok, I'm probably showing my ignorance here but I'll ask some questions that might at least serve as a learning tool for those following along. I"m basing my comments on the sample server and client. I have no idea how qtmspin may have altered the programs for his work. And as I said above, it's literally been years since I did socket programming and then it was on unix, not Windows.

Asynch sockets are complicated. Doesn't the server need to handle on FD_WRITE event so that it knows when it's ok for it to write to the socket? By using WSAAsyncSelect you've ensured that the send command won't block when a buffer is full or anything else that would otherwise make it wait, so the FD_WRITE message handler should be used so that we know it's ok to send.

Again, I'm far from an expert but I think you need a few other message handlers setup and need some error handling after the send command. Right now no checking is being done to know whether the send was successful or not.

I did a quick search and found this little primer on basic asynch socket programming, and includes a better explanation of the FD_WRITE event handling. http://www.gamedev.net/reference/articles/article1297.asp
Back to top
View user's profile Send private message
qtmspin



Joined: 17 Oct 2006
Posts: 23

PostPosted: Sat Dec 30, 2006 1:21 pm    Post subject: newish received data Reply with quote

I have two sub-routines work with the data now. If the subroutines are working with the data while more data is received, will the received data be ignored? Or are the surroutines treated seperatetly (different thread?) then the Received Data function?


Code:
ReceiveData(wParam, lParam)
; By means of OnMessage(), this function has been set up to be called automatically whenever new data
; arrives on the connection.
{
   global ShowRecieved
   global ReceivedData
   
   Gui, Submit, NoHide   
   socket := wParam
   
    ReceivedDataSize = 4096 ; Large in case a lot of data gets buffered due to delay in processing previous data.
    Loop  ; This loop solves the issue of the notification message being discarded due to thread-already-running.
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
        ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
        if ReceivedDataLength = 0  ; The connection was gracefully closed,
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        if ReceivedDataLength = -1
        {
            WinsockError := DllCall("Ws2_32\WSAGetLastError")
            if WinsockError = 10035  ; WSAEWOULDBLOCK, which means "no more data to be read".
                return 1
            if WinsockError <> 10054 ; WSAECONNRESET, which happens when Network closes via system shutdown/logoff.
                ; Since it's an unexpected error, report it.  Also exit to avoid infinite loop.
                MsgBox % "recv() indicated Winsock error " . WinsockError
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        }
        ; Otherwise, process the data received.
        ; Msgbox %ReceivedData%
        Loop, parse, ReceivedData, `n, `r
        {
              ReceivedData=%A_LoopField%
              if (ReceivedData!="")
              {
            GoSub ParseData
            GoSub UseData
         }
        }   
   }
    return 1  ; Tell the program that no further processing of this message is needed.
}
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10716

PostPosted: Sat Dec 30, 2006 2:45 pm    Post subject: Reply with quote

You're probably already aware of the Critical command. It will buffer incoming messages to prevent them from being dropped when a subroutine takes too long to finish. The remarks on the OnMessage page give some details about this.
Back to top
View user's profile Send private message Send e-mail
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 5:19 pm    Post subject: Reply with quote

I did some testing on my own. I learned a little bit, but I'm not sure what. Smile

I modified the server to send the text in a loop i number of times, and to do so with a delay of j ms, implemented with sleep, j. I modified the gui so that I could specify both i and j. I tested with client and server running on the same computer.

The send code is very simple and is shown below. I did not implement an FD_WRITE event, hoping to prove send() would fail if called in a loop too quickly. I thought for sure I'd receive a WSAEWOULDBLOCK error if the loop was too quick.

Code:
   Loop % Repeat
   {
      sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
      WinsockError := DllCall("Ws2_32\WSAGetLastError")
      if WinsockError <> 0
         MsgBox % "send() indicated Winsock error " . WinsockError
      sleep,Delay
   }   


I added Critical to the first line of the client's ReceiveData routine so it couldn't be interrupted, and modified the receive loop to loop on recv() until there was no data left, and then process it. The code is as follows:

Code:
ReceiveData(wParam, lParam)
; By means of OnMessage(), this function has been set up to be called automatically whenever new data
; arrives on the connection.
{
     Critical
    global ShowReceived
    global MyEdit
    global LinesReceived
    Data=
    socket := wParam
    ReceivedDataSize = 4096  ; Large in case a lot of data gets buffered due to delay in processing previous data.
    Loop  ; This loop solves the issue of the notification message being discarded due to thread-already-running.
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
        ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
        if ReceivedDataLength = 0  ; The connection was gracefully closed,
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        if ReceivedDataLength = -1
        {
            WinsockError := DllCall("Ws2_32\WSAGetLastError")
            if ( WinsockError = 10035 ) { ; WSAEWOULDBLOCK, which means "no more data to be read".
                break
            }
            if WinsockError <> 10054 ; WSAECONNRESET, which happens when Network closes via system shutdown/logoff.
                ; Since it's an unexpected error, report it.  Also exit to avoid infinite loop.
                MsgBox % "recv() indicated Winsock error " . WinsockError
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        }
        Data .= ReceivedData
    }
    ; process the data received.
    Loop, parse, Data, `n, `r
    {
       LinesReceived++               
        if (LinesReceived = 1) {
           ShowReceived = %LinesReceived%: %A_LoopField%
        } else {
           ShowReceived = %ShowReceived%`n%LinesReceived%: %A_LoopField%
       }
       ;Tooltip % ShowReceived
       GuiControl,, MyEdit, %ShowReceived%
    }
    return 1  ; Tell the program that no further processing of this message is needed.
}



With a repeat of 5 and a delay of 1ms I still received all messages on the client. With a delay of 0 ms the client would usually receive 3 out of 5, though at times the text of 2 messages would be part of one receive on the client end. If I commented out the sleep command altogether, the client would receive just 1 message.

Neither send() or recv() ever return an error status. The fact that some data is being lost but no error status returned tells me there's a coding mistake somewhere, but I don't know where it is.
Back to top
View user's profile Send private message
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 5:22 pm    Post subject: Reply with quote

I found another nice site for info on Winsock programming: http://tangentsoft.net/wskfaq/
Back to top
View user's profile Send private message
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 5:39 pm    Post subject: Reply with quote

So I did some more testing, adding a counter to the messages I sent so that I could see which ones were being lost. I wish I could explain this.



I'd love to know what is going on.
Back to top
View user's profile Send private message
qtmspin



Joined: 17 Oct 2006
Posts: 23

PostPosted: Sat Dec 30, 2006 6:24 pm    Post subject: Reply with quote

Great work, I love it! Have you tried hooking telnet up to the server, its easy and gives great feedback - although I am not sure if it's 100% accurate...

Im sure you know this already but...
start - run - telnet
in telnet type in open 192.168.0.x and the port of the server
Back to top
View user's profile Send private message
wtg



Joined: 04 Oct 2006
Posts: 210
Location: Louisville, KY

PostPosted: Sat Dec 30, 2006 7:07 pm    Post subject: Reply with quote

qtmspin wrote:
Great work, I love it! Have you tried hooking telnet up to the server, its easy and gives great feedback - although I am not sure if it's 100% accurate...

Im sure you know this already but...
start - run - telnet
in telnet type in open 192.168.0.x and the port of the server


Ah, no I hadn't. Forgot all about doing that even though I saw your discussion above.

Doing so shows that all the messages are being sent. Telnet receives them all easily, even with a delay of 0 and a large repeat count. So, it's something on the receiving side. I'm pretty new to AHK and I've not used the Critical command before so perhaps I'm doing something wrong.

As it is now, it seems there's a bug on the receiving side or there's a problem with AHK's message handling and messages are being missed. It's probably the code. =)
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9  Next
Page 2 of 9

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group