Android Question Can a socket be connected and closed at the same time?

Discussion in 'Android Questions' started by Sandman, Jun 28, 2018.

Tags:
  1. Sandman

    Sandman Well-Known Member Licensed User

    I whipped up some code to help out with a little logging, but surprisingly often it crashes with java.io.IOException: Socket Closed in the line commented with CRASH HERE. I've wrapped everything carefully to make sure the socket should be in good shape, but even though it apparently is connected, it's considered closed in the line after. How is this even possible? Am I missing something obvious?

    logThis_Error and logThis_Terminated are never called.

    And on the receiving end is just a dead simple receiver that dumps out whatever is sent to it, so I'm very sure that side isn't part of the problem. (It's just the command ncat -k -l 5010 running on a Linux machine.)

    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.
        ' For logging purposes only
        Private socket As Socket   
    End Sub


    Public Sub logThis (text As String)
       
        
    Dim astream As AsyncStreams
        
    Dim data() As Byte
        
    Dim Successful As Boolean = False

        
    If Not(socket.IsInitialized) Then
            
    socket.Initialize("socket")
        
    End If

        
    If Not(socket.Connected) Then
            
    socket.Connect("192.168.1.14"501030000)
            
    Wait For socket_Connected (Successful As Boolean)
        
    End If
       
        
    ' Exit early if it wasn't successful
        If Not(Successful) Then
            
    Log("logThis: Not successful")
            
    Return
        
    End If

        
    If socket.Connected Then
            astream.Initialize(
    Nullsocket.OutputStream, "logThis"' <-- CRASH HERE
            data = (text & CRLF).GetBytes("UTF8")
            astream.Write(data)
        
    Else
            
    Log("logThis: COULD NOT CONNECT")
        
    End If
       
    End Sub


    Public Sub logThis_Error
        
    Log("logThis: ERROR")
        
    If LastException.IsInitialized Then
            
    Log(LastException.Message)
        
    Else
            
    Log("LogThis: No exception message available")
        
    End If
    End Sub


    Public Sub logThis_Terminated
        
    Log("logThis: TERMINATED")
        
    If LastException.IsInitialized Then
            
    Log(LastException.Message)
        
    Else
            
    Log("LogThis: No exception message available")
        
    End If
    End Sub
     
  2. Didier9

    Didier9 Active Member Licensed User

    Yes, if it is a Schrödinger socket...
     
    KMatle, JordiCP and Diceman like this.
  3. Diceman

    Diceman Active Member Licensed User

    I'm no expert, but shouldn't you be executing aStream.InitializePrefix instead of aStream.Initialize?
    See https://www.b4x.com/android/forum/threads/b4x-asyncstreams-tutorial.7669/#content

    Or you could follow Didier9's suggestion and see if the malfunctioning socket killed Schrödinger's cat.
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    Your code will create a new AsyncStreams every call. This is a mistake. Initialize AsyncStreams once after the socket is connected.
     
  5. Sandman

    Sandman Well-Known Member Licensed User

    Ok, I'll try that, thanks.


    But how can this be a mistake? Is the AsynchStreams more tightly coupled to the socket than what can be expected from my code? As the AsynchStream is defined in the sub, I thought it would cease to exist once the sub ends, causing the socket to also lose its reference to it. Now I'm starting tu suspect that the socket doesn't release the reference, which means my code just keeps adding more and more AsynchStreams to the socket, causing problems.
     
  6. Sandman

    Sandman Well-Known Member Licensed User

    Only if I want Prefix mode.
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    That's a mistake. Objects are "killed" when there are no more live references to them. In this case AsyncStreams will never be killed as it creates two threads that work with the socket and hold reference to the AsyncStreams object.
     
  8. Sandman

    Sandman Well-Known Member Licensed User

    That makes perfect sense. I have no idea why I thought the sub had more power than the reference, thanks for explaining.

    Sidenote... I wonder how many hard-to-find bugs happen because one does what I did: Define one variable as a process global, and then another in a sub, and using the sub one in the process one. (I wonder if this is something the linter could catch in a reasonably simple way.)
     
  9. Diceman

    Diceman Active Member Licensed User

    I don't know if this can help you or not.
    I always define my local variables with a prefix like "loc" for "locStream" (or perhaps "lstream") and parameters passed to a sub start with "a" as in "aStream". I don't normally use a prefix on global variables, or you could use "gblStream" or "gStream" etc. Just by looking at the variable you know where it is defined. It makes debugging much much easier and I'm not tearing my hair out wondering what the scope of the variable is. I could never go back to programming without using variable prefixes.

    I used to use "_" as the prefix for local variables in a different language so local variables are like "_Stream" and is very readable, but the "_" disables obfuscation in some B4x subs. :(
     
    Sandman likes this.
  10. Sandman

    Sandman Well-Known Member Licensed User

    Me neither, but thanks for the suggestion! I'm going to let it marinate for a while to see what makes sense for me...
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice