Comunicating with a Telnet Server

Discussion in 'Questions (Windows Mobile)' started by lu_ozzie, Nov 6, 2007.

  1. lu_ozzie

    lu_ozzie New Member Licensed User

    My question is, can I comunicate with a telnet server? I have a PPC application and i need to write and read string of text with a telnet server...
    I'm trying to use Network.dll and BinaryStream.dll, but I don't have enough info and I don't know how to deal with these classes...
    Any suggestion or example will be very appreciate! :confused:
    Thanks!
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    Do you know the server's IP?
    Create a Client object and connect to this IP (use port 23):
    Don't forget to add a reference to the Network library and add a Client object named client.
    Code:
    [LEFT][FONT=Courier New][COLOR=#0000ff]Sub [/COLOR][/FONT][FONT=Courier New][COLOR=#010101]App_Start[/COLOR][/FONT]
    [
    FONT=Courier New][COLOR=#010101]      client.New1[/COLOR][/FONT]
    [
    FONT=Courier New][COLOR=#010101]      client.Connect("xxx.xxx.xxx.xxx",23) [/COLOR][/FONT][FONT=Courier New][/FONT]
    [
    FONT=Courier New][/FONT][FONT=Courier New][COLOR=#0000ff]msgbox[/COLOR][/FONT][FONT=Courier New][COLOR=#010101]("Client connected.")[/COLOR][/FONT]
    [
    FONT=Courier New][COLOR=#010101]      client.Close[/COLOR][/FONT][/LEFT]
    [
    FONT=Courier New][COLOR=#0000ff]End Sub
    [/COLOR][/FONT]
     
  3. lu_ozzie

    lu_ozzie New Member Licensed User

    Ok, that's what i did... and it connects properly...
    My biggest problem was the dialogue with the tother computer after connecting..
    That's what i did:
    Code:
    Sub Connect(IP)
       
    'ErrorLabel(errConnect)
       WaitCursor(true)
       TextBox2.Text = 
    "Connecting to " & IP
       
    Dim client
       client.New1
       client.Connect(IP,
    23)
       stream.New1(client.GetStream,
    true)
       TextBox2.Text = 
    "Connection established."
       
    Return
    End Sub
    I'm trying to read something from the server...I need to write sentences and read replies... Thanks for the quick answer! :)
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    You should remove the Dim client line.
    Did you add a BinaryFile object named stream?
    See this example:
    You should add a Bitwise object named bit.
    Code:
    Sub Globals
        
    Dim buffer(0As byte
    End Sub

    Sub App_Start
        
    bit.New1
        AddTimer(
    "Timer1")
        Timer1.Interval = 
    500
    End Sub

    Sub Connect(IP)
        
    'ErrorLabel(errConnect)
        WaitCursor(true)
        TextBox2.Text = 
    "Connecting to " & IP
        client.New1
        client.Connect(IP,
    23)
        stream.New1(client.GetStream,
    true)
        TextBox2.Text = 
    "Connection established."
        timer1.Enabled = 
    true
        WaitCursor(
    false)
    End Sub

    Sub Timer1_Tick
        
    If client.DataAvailable Then
            
    Dim buffer(4096As byte
            count = stream.ReadBytes(buffer(),
    4096)
            TextBox2.Text = 
    bit.BytesToString(buffer(),0,count)
        
    End If
    End Sub
     
  5. TWELVE

    TWELVE Active Member Licensed User

    Hello Erel,

    i don't wanna highjack this thread, but i've got a question regardings this.

    That piece never works for me:

    Code:
    Sub Timer1_Tick
       [COLOR=
    "Red"If client.DataAvailable Then[/COLOR]        Dim buffer(4096As byte
            count = stream.ReadBytes(buffer(),
    4096)
            TextBox2.Text = 
    bit.BytesToString(buffer(),0,count)
        
    End If
    End Sub
    The line

    If client.DataAvailable Then
    ..
    end if

    gets never triggered and therefore i never catch the server's response.If i remove this check, i can read the server's response but run risk to get stuck because there's maybe no answer from the server pending anymore .


    cheers

    TWELVE
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    It's strange. DataAvailable should return the correct value.
    See the ChitChat example which uses it.
     
  7. agraham

    agraham Expert Licensed User

    I can confirm that DataAvailable should work. I've used it in two apps so far, on the device and desktop. If the Dim Buffer... line really is there maybe it's upsetting things even if it does get through the compiler. Dim should only go in Globals.
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    Small correction, it is fine (and many times necessary) to use the Dim keyword to redimension an array which was declared in Sub Globals.
     
  9. agraham

    agraham Expert Licensed User

    Sorry. :sign0013: You are right Erel, as usual. I had overlooked that possibility
     
  10. TWELVE

    TWELVE Active Member Licensed User

    I'll have a look at it again...

    Cheers

    TWELVE
     
  11. TWELVE

    TWELVE Active Member Licensed User

    Still no success with your code.I just copied the timer part and it does not catch any data from the network, with the result, that my routine is exiting because the server did not respond the way it expected.

    Furthermore i can't see the advantage of the timer here..if you issue a command against a server in a certain protocol language, you have to wait for the server's response because depending on the answer you will decide how to proceed.Even if the timer does catch the answer, it does not help as long as my routine does not wait for the answer, because it's crucial for further processing.

    If the task is to get a telnet server response into a command line style window, timing is not important and also the server's response doesn't matter, if there's no one who is waiting for a certain answer.

    Providing you've got a fast network connection...your timer has an interval of 500ms setup.So 500ms goes by, before the timer is activated the first time.Can you imagine, how long 500ms in terms of networks is...? Server connections with 500ms delay are supposed to be very high latency connections.The latency to my mail server is 8ms.So you never will catch up a server response unless you lower your timer interval.

    Beside this it appears like it takes far too long to start the timer the first time, whatever i use for the interval.I built in a function printing out something within the timer code.This does come up after my routine exited for "long" time.

    So, for me and at this time only works to retrieve the server's reponse right after i sent the command to server and this only, if i strip of the client.DataAvailable thingy.

    This looks then like this:

    Code:
    Sub asub

    ...
     s = 
    "a command against the server"     
         netwritebuffer() = 
    bit.StringToBytes(s,0,StrLength(s))
        stream.WriteBytes(netwritebuffer())
    ...

    GetServerResponse()

    if expected response then

    ...
    do the next command
    ...

    end if

    no success

    End Sub

    ...

    Sub GetServerResponse

     
    'If client.DataAvailable Then 
         Dim bufferbits(4096As byte
         count = stream.ReadBytes(bufferbits(),
    4096)
         buf = 
    bit.BytesToString(bufferbits(),0,count)
         
    Return buf
    ' End If

    End Sub
    If i remove the ticks in front of client.DataAvailable and Endif, i never get the response ( even though i can see the correct response by the server in a network trace...) and therefore exit the sub.


    So this looks more complicated as it appears to look.I personally don't think the client.DataAvailable does not work, rather i think it has to do with timing.Can you explain me, what advantage the use of a timer has in that case, given the fact that the "sender part" has to wait for the response anyhow..? For me that looks this way: i setup a timer that polls something and i poll then, if the timer got already the result..? This makes no sense, and given the fact that the timer does not run in parallel it makes even less sense...?

    Usually this would be handled this way:

    ..
    Send something
    setup callback: wait for network response & call me as soon as result is available at CB_resume
    go to sleep...zzz..zzzz..zzzz
    ..
    CB_resume:
    Yas i got an answer and can proceed
    ...



    So for now i'm a little bit confused and need investigate this further...any suggestions..?


    cheers

    TWELVE
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    After a connection is established between a client and a server no data can get lost.
    It doesn't matter if you read the data immediately or not. The data is buffered.
    If you try to read data before it arrived the process will be blocked until data arrives.

    In the case of the ChitChat example the Timer and the DataAvailable check are required to prevent blocking.
    You must use a timer or some other polling mechanism if you are checking DataAvailable.
     
  13. agraham

    agraham Expert Licensed User

    Check this link http://www.basic4ppc.com/forum/showthread.php?t=1130 for another example of a client/server example using timers and DataAvailable. Start an instance on your desktop as a server, start aother as a client and they should talk to each other. One thing to note is the loop on DataAvailable in the timer loop, you still get the timer latency but once data starts arriving you suck it all out before exiting.
     
  14. TWELVE

    TWELVE Active Member Licensed User

    Hello Erel & agraham,

    i did further testing and was successful in getting my code working, but..I'm still having issues with the client.DataAvailable.


    I was able to get this here to work:


    Code:
    Sub MySub
    ...

    send something 
    to the server
    GetNetworkResponse
    make a decision depending on buf

    ...
    End Sub

    Sub GetNetworkResponse
                         
    Do Until client.DataAvailable = true
          Sleep(
    300)
                
    Loop
          
          
          
    Dim bufferbits(4096As byte
          count = stream.ReadBytes(bufferbits(),
    4096)
          buf = 
    bit.BytesToString(bufferbits(),0,count)
          
    Return buf      
        
    End Sub

    So far so good.But if i change the time in Sleep() to more than 300, the program will deadlock within the Loop.This is because the client.DataAvailable never becomes true.You mentioned above, that the time does not matter for this function.So i could - theoretically - execute client.DataAvailable at the end of my program and would get back a true ( yes there's data i received from the server) and could then retrieve this data - if the server ever responded someting.

    So..why does my code above not work anymore if the sleep() is set higher than 300...? I do not have an explanation for that, do you..?

    If i add a counter, which exits the loop after a certain number of cycles, everything works ok:


    Code:
    Sub GetNetworkResponse
                              x=
    1
          buf = 
    ""
                  
    Do Until client.DataAvailable = true
          Sleep(
    500)
          x = x+
    1
              
    If x > 50 Then
              
    Return
              
    End If
       
    Loop
             
          
    Dim bufferbits(4096As byte
          count = stream.ReadBytes(bufferbits(),
    4096)
          buf = 
    bit.BytesToString(bufferbits(),0,count)
          
    Return buf
    End Sub
    If the condition persists, the if..then needs to break the loop after the specified maximum number of loop cycles...and if this occurs, the buf has the correct server response stored.So the answer was there, but the client.DataAvailable prevent the loop from finishing, so it loops for ever.



    To circumvent that problem, i use then this code :


    Code:
    x=1
                       buf = 
    ""
          
          
    Do While buf = "" 
          x = x+
    1
    '      If x > 20 Then
    '      Return
    '      End If
          
          
          
    Dim bufferbits(4096As byte
          count = stream.ReadBytes(bufferbits(),
    4096)
          buf = 
    bit.BytesToString(bufferbits(),0,count)
          Sleep(
    500)
                              
    Loop
          
    Return buf
    end sub

    It just reads the buffer in a loop, until the buffer (buf) is different from an empty string.To prevent a deadlock from happening, if there is no answer from the server, i built in the If...then which is ending the loop after a certain number of cycles.

    So i assume then: data.ClientAvailable is working in general, but sometimes it does not.I suspect it happens when the retrieved server response is not complete yet.

    This would the look like this:

    i send some request data to the server ( netwritebuffer() = bit.StringToBytes(s,0,StrLength(s)) )
    after 100ms i check client.DataAvailable
    client.DataAvailable is true
    ==> i retrieve the server response
    the server is sending more response data
    after 100ms i check client.DataAvailable
    client.DataAvailable is false
    If i rely on the client.DataAvailable ==> loop is infinite now
    if i just retrieve the data, the buffer contains what i was looking for.

    This probably happens, if the delay betweens checks is shorter than the server needs to send the complete answer.Since i cannot know the server's response time in advance and i don't know, if the server has completed its answer, i have either to check, if i can expect more data from server or i have to set a time out, after which i will give up waiting.

    For this, i've to rely on the client.DataAvailable or i can do a cyclic stream.ReadBytes until i get a non-empty string or the timeout is reached.

    Therefore my guess is, client.DataAvailable does indicate the first data received after a netwritebuffer(), but if the server sends more packets after the first data ( which was indicated by client.DataAvailable) had been retrieved using stream.ReadBytes, any subsequent reply packet is then not indicated by the the client.DataAvailable any more.


    I took now the first code example, added the cycle count check as a timeout and complemented the Do Until..Loop check with "OR (buf <> "")", which prevents the code from running unnecessary loops passes:


    Code:
    Sub GetNetworkResponse
                              x=
    1
          buf = 
    ""
                  
    Do Until client.DataAvailable = true OR (buf <> "")
          Sleep(
    500)
          x = x+
    1
              
    If x > 50 Then
              
    Return
              
    End If
       
    Loop
             
          
    Dim bufferbits(4096As byte
          count = stream.ReadBytes(bufferbits(),
    4096)
          buf = 
    bit.BytesToString(bufferbits(),0,count)
          
    Return buf
    End Sub

    @Erel: please can you have a look at this behavior, why the client.DataAvailable does not indicate subsequent packets from the server, while i can read them anyhow..?


    regards

    TWELVE
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    I don't know why it doesn't work with Sleep > 300.
    DataAvailable checks whether there is data waiting in the network buffer.

    Writing and reading from the network stream is a blocking operation.
    When you try to read from the stream the program is blocked until data arrives.
    It is possible that DataAvailable returns false and still you can read from the stream (which will cause a small internal waiting).

    I'm not sure you should use DataAvailable at all in your case.
    If you expect to receive a message after sending one you should just read from the stream.
    Remember that the server socket can also get blocked waiting for you to read the first message.
     
  16. agraham

    agraham Expert Licensed User

    This is my Sub from a Request/Response app that has been running for months on several different computers and OSs. We have noticed that different computers seem to suffer from different numbers of timeouts which we have up to now put down to network problems as the server is situated in a cottage overlooking the Irish Sea with ADSL delivered over overhead phone lines subject to salt spray and so whose connections can be a little iffy. It normally sleeps for 50mS between checks but I have just tried 500mS and 1000mS and it works fine first time, but my computer always does. I don't have access to the other computers that appear to need several retries most of the time.

    Maybe these differences are due to something like this DataAvailable problem. I've looked with Reflector and the DataAvailable call ends up calling the native OS ioctlsocket() function to get the number of bytes available to read from the socket. I can't look any deeper than that.

    Code:
    Sub NetGetData(req)
       msg =
    "An error occurred connecting to " & URL
       ErrorLabel(
    "err2")
       Client.New1
      Client.Connect(URL, Port)
      Stream.New1(Client.GetStream,
    true
       msg = 
    "GET /" & req & " HTTP/1.1" & Crlf 
       msg = msg & 
    "Host: " & URL & Crlf
       msg = msg & 
    "Proxy-Connection: Keep-Alive" & Crlf
       msg = msg & 
    "Pragma: no-cache" & crlf
       
    If Secure Then
          p = StringToBase64(User & 
    ":" & password)
          msg = msg & 
    "Authorization: Basic " & p & Crlf
       
    End If
       msg = msg & 
    Crlf   
       WebReq() = Stream.StringToBytes(msg)   
       Stream.WriteBytes2(WebReq(),
    0,StrLength(msg))
       
    Timer = 0
       
    Do
          Sleep(SleepMs)
          
    Timer = Timer + SleepMs
          
    If Timer >= Timeout Then
             
    Return    "A timeout occurred communicating with " & Device
          
    End If
       
    Loop Until Client.DataAvailable = true
       count = Stream.ReadBytes(WebResp(),
    4096)
       msg = Stream.BytesToString (WebResp(), 
    0, Count)
      Client.Close
       
    If SubString(msg, 13,2) = "OK" Then
          msg = SubString(msg, 
    44, StrLength(msg)-44)
       
    Else
          msg = 
    "Badly formatted data received from " & Device
       
    End If   
       err2:
       
    If ChkDebug.Checked Then   
          
    Msgbox(msg,"Message data received")
       
    End If
       
    Return msg
    End Sub
     
  17. schimanski

    schimanski Well-Known Member Licensed User

    I think, thats my old problem!

    Hello TWELVE!

    My english is not as good, that I can understand everything of your thread, but I think, you have a simular problem, that I have. Perhaps, you have a look at my thread:

    http://www.basic4ppc.com/forum/showthread.php?t=1318

    I haven't found an answer for my problem until today, but I also have noticed, that client.dataavailable is affected from the timerinterval. Do you know, how i can eliminate a lock up of my application, when the server sends no data? You have experienced a lot and you have perhaps found some answers to avoid the problem.

    Thanks a lot....:sign0085:
     
Loading...