B4J Question TCP Socket Server works but I've done something wrong!

Discussion in 'B4J Questions' started by vfafou, Apr 1, 2015.

  1. vfafou

    vfafou Active Member Licensed User

    Hello!
    I'm trying to implement a TCP Sockets Server for use on my LAN.
    I had written the shared code inside the Main Sub and it was working.
    I tried to move the shared code inside a new code module. Since moving the code to another module, I can't connect to the socket server. Init sub is called from Main.
    The sockets created are derived from a Class module.
    What am I doing wrong?
    Note that I need every socket running at its own thread!

    Thank you in advance!

    The shared module code:
    Code:
    Sub Process_Globals
        
    'Global statistics.
        Private intActiveClients As Int
        
    Private intMessages As Int
        
    Private intBytes As Int
      
        
    Public  srvListener As ServerSocket
        
    Public  IsListening As Boolean
        
    Dim     intPort As Int
        
    Private lstClients As List
      
    End Sub

    Private Sub srvListener_NewConnection(Successful As Boolean, NewSocket As Socket)
        
    Dim intClient As Int
        
    Dim RMC As RMClient
        
    Dim FoundAvailable As Boolean
        
    Dim intActualClient As Int
        
    Dim NewClient As RMClient
      
        
    If Successful Then
            
    'Socket1 = NewSocket
          
            
    For intClient = 0 To lstClients.Size - 1
      
                RMC = lstClients.Get(intClient)
              
                
    If Not(RMC.InUse) Then
                    FoundAvailable = 
    True
                    
    'Hack needed here to emulate action of
                    'an "Exit For" statement:
                    intActualClient = intClient
                    intClient = lstClients.Size - 
    1
                
    End If
              
            
    Next
          
            
    If Not(FoundAvailable) Then
                intActualClient = intClient
                NewClient.Initialize(Me, 
    "Client", intActualClient)
                lstClients.Add(NewClient)
                RMC = NewClient  
            
    End If
          
            RMC.NewConnection(NewSocket)
            intActiveClients = intActiveClients + 
    1
            
    Log("Client " & intActualClient & " connected")
          
        
    Else
            
    Log("Connection attempt failed: " & LastException.Message)
        
    End If
      
        srvListener.Listen

    End Sub

    Public Sub RMClient_Input(strMsg As String)
        
    Dim intClient As Int
        
    Dim Client As RMClient
      
        intMessages = intMessages + 
    1
       
        
    For intClient = 0 To lstClients.Size - 1
            Client = lstClients.Get(intClient)
      
            
    If Client.InUse Then
                Client.Write(strMsg & 
    Chr(0x0d))
            
    End If
      
        
    Next

    End Sub

    Private Sub RMClient_Bytes(ReceivedByteCount As Int)
        intBytes = intBytes + ReceivedByteCount
        
    Log(intBytes)
    End Sub


    Public Sub Init
        intPort = 
    61999
        srvListener.Initialize(intPort, 
    "srvListener")
        srvListener.Listen
        
    Log("Listening on port " & intPort)
        lstClients.Initialize
        IsListening = 
    True
    End Sub


    Private Sub StopServer
        
    Dim intClient As Int
        
    Dim Client As RMClient
      
        
    For intClient = 0 To lstClients.Size - 1
            Client = lstClients.Get(intClient)
            
    If Client.InUse Then
                Client.Close
            
    End If
        
    Next
        srvListener.Close
        IsListening = 
    False
    End Sub
    The Class code:
    Code:
    Private Sub Class_Globals
        
    'PseudoConsts:
        Private DELIMITER As String = Chr(0x0d'CR.
        Private ENCODING As String = "WINDOWS-1253"
        
    Private INPUT_STREAM_FALLBACK As Int = 18000
        
    Private INPUT_STREAM_MAX As Int = 22000 'This can be ineffective if not
                                                'greater than underlying socket
                                                'buffer length (normally 8192
                                                'bytes).
      
        
    Private mParent As Object
        
    Private mEventName As String
        
    Private mIndex As Int
        
    Private mInput As String
        
    Private mInUse As Boolean
        
    Private mLastError As String
      
        
    Public  mClientType As Int         ' 1 = Statuses, 2 = WorkStations, 3 = AnswerStatuses
        Private mClientBase As String  ' CD_BASE
      
        
    Private sckClient As Socket
        
    Private astmClient As AsyncStreams
        
    Private sbAssemStm As StringBuilder 'Assembled input stream buffer.
      
        
    Private Strings As JStringFunctions
      
    End Sub


    Public Sub Initialize(Parent As Object, EventName As String, Index As Int)
        mParent = Parent
        mEventName = EventName
        mIndex = Index
      
        Strings.Initialize
      
    End Sub


    Public Sub getIndex() As Int
        
    Return mIndex
    End Sub


    Public Sub getInput() As String 'Valid during Input event.
        Return mInput
    End Sub


    Public Sub getInUse() As Boolean
        
    Return mInUse
    End Sub


    Public Sub getLastError() As String
        
    Return mLastError
    End Sub


    Public Sub Close()
        astmClient.Close
        sckClient.Close
        sckClient = 
    Null
        
    CallSub2(mParent, mEventName & "_Terminated", Me)
        mInUse = 
    False
    End Sub


    Public Sub NewConnection(NewSocket As Socket)
        mLastError = 
    ""
        sckClient = NewSocket
        sbAssemStm.Initialize
        astmClient.Initialize(sckClient.InputStream, sckClient.OutputStream, 
    "astmClient")
        mInUse = 
    True
    End Sub


    Public Sub Write(Output As String)
        
    Dim mCMesg As String
        
    Dim mCBase As String
      
        
    Try
            
    'Log(Output)
            'Log(mClientType)
            Select Case mClientType
                
    Case 1
                    astmClient.Write(Output.GetBytes(ENCODING))
                    
    'astmClient.Write(DELIMITER.GetBytes(ENCODING))
            
            
    End Select
          
        
    Catch
            
    Log("Error Client Write!")
        
    End Try
    End Sub

    Private Sub astmClient_Error()
        mLastError = 
    LastException.Message
        
    CallSub2(mParent, mEventName & "_Error", Me)
        
    Log(mLastError)
        Close
    End Sub

    Private Sub astmClient_NewData(Buffer() As Byte)
        
    Dim Frag As String
        
    Dim Msgs As String
        
    Dim Pos As Int
        
    Dim DelimPos As Int
      
        
    Dim RmID As String
        
    Dim RmMesg As String
      
        
    CallSub2(mParent, mEventName & "_Bytes", Buffer.Length)
      
        Frag = 
    BytesToString(Buffer, 0, Buffer.Length, ENCODING)
      
        
    If sbAssemStm.Length > INPUT_STREAM_MAX Then
            sbAssemStm.Remove(INPUT_STREAM_FALLBACK, sbAssemStm.Length)
        
    End If
      
        sbAssemStm.Append(Frag)
      
        
    If Frag.Contains(DELIMITER) Then
          
            Msgs = sbAssemStm.ToString
          
            Pos = 
    0
          
            
    Do Until DelimPos < 0
                DelimPos = Msgs.IndexOf2(DELIMITER, Pos)
                
    If DelimPos >= 0 Then
                    mInput = Msgs.SubString2(Pos, DelimPos)
                  
                    RmID = Strings.SplitGetWord(mInput, 
    ","1)
                    RmMesg = Strings.SplitGetWord(mInput, 
    ","2)
                  
                    
    Log(mInput)
                  
                    PushShared.SendWebClientMessage(RmMesg, RmID)
                    
                    mInput = 
    ""
                    Pos = DelimPos + 
    1
                
    End If
            
    Loop
          
            
    'Delete the processed messages from the assembled input stream,
            'reinsert any leftover characters.
            sbAssemStm.Initialize
            sbAssemStm.Append(Msgs.SubString(Pos))
          
        
    End If
      
    End Sub

    Private Sub astmClient_Terminated()
        Close
    End Sub
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    What happens when you run the program? Does NewConnection event fire?

    When you use AsyncStreams each socket is managed by its own thread. However your code runs in the main thread.

    The only way to completely manage each connection with its own thread is with a real server built with jServer library.
     
  3. vfafou

    vfafou Active Member Licensed User

    Hello Erel!
    Yes, NewConnection event fire but I have a strange behavior, like confused clients and multiple times message sending.
    The behavior before this post was like not connected!
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    lemonisdead likes this.
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