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


Well-Known Member
Licensed User
Longtime User
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:
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
        If Not(FoundAvailable) Then
            intActualClient = intClient
            NewClient.Initialize(Me, "Client", intActualClient)
            RMC = NewClient  
        End If
        intActiveClients = intActiveClients + 1
        Log("Client " & intActualClient & " connected")
        Log("Connection attempt failed: " & LastException.Message)
    End If

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

End Sub

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

Public Sub Init
    intPort = 61999
    srvListener.Initialize(intPort, "srvListener")
    Log("Listening on port " & intPort)
    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
        End If
    IsListening = False
End Sub

The Class code:
Private Sub Class_Globals
    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
    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
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()
    sckClient = Null
    CallSub2(mParent, mEventName & "_Terminated", Me)
    mInUse = False
End Sub

Public Sub NewConnection(NewSocket As Socket)
    mLastError = ""
    sckClient = NewSocket
    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
        Select Case mClientType
            Case 1
        End Select
        Log("Error Client Write!")
    End Try
End Sub

Private Sub astmClient_Error()
    mLastError = LastException.Message
    CallSub2(mParent, mEventName & "_Error", Me)
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
    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)
                PushShared.SendWebClientMessage(RmMesg, RmID)
                mInput = ""
                Pos = DelimPos + 1
            End If
        'Delete the processed messages from the assembled input stream,
        'reinsert any leftover characters.
    End If
End Sub

Private Sub astmClient_Terminated()
End Sub


B4X founder
Staff member
Licensed User
Longtime User
What happens when you run the program? Does NewConnection event fire?

Note that I need every socket running at its own thread!
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.
Upvote 0


Well-Known Member
Licensed User
Longtime 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!
Upvote 0