Socket client/server

kent

Member
Licensed User
Longtime User
Hi,

I’m working on a project where a PC/vb.net program and an android program must be able to send information to each other(in the future with more than one android device). They don’t necessarily have to be connected all the time.

The communication must be able to be started from both devices. – So I guess that both devices have to act as both server and client ? (Or what ?)

I have with help for the forum managed to make the first way: android as server and vb.net as client.

PC->android:

Android server:


B4X:
Service module
Sub Process_Globals
   
Dim ServerSocket1 As ServerSocket 
Dim Socket1 As Socket  
Dim Timer1 As Timer   
Dim InputStream1 As InputStream 
Dim OutputStream1 As OutputStream  
Dim RefreshDataFlag_1,RefreshDataFlag_2 As Boolean 
Dim param_over As String
Dim MP2 As MediaPlayer 
End Sub
Sub Service_Create
'If FirstTime Then     
   Timer1.Initialize("Timer1", 2000)     
'End If  

If ServerSocket1.IsInitialized = False Then 
   ServerSocket1.Initialize(2222, "ServerSocket1")  
   Log("server-socket initialiseret")
End If  
End Sub

Sub Service_Start (StartingIntent As Intent)
Log("My IP: " & ServerSocket1.GetMyIP)
ServerSocket1.Listen
End Sub

Sub Service_Destroy
   Timer1.Enabled = False  
   Socket1.Close      
   ServerSocket1.Close 'stop listening  
End Sub

Sub ServerSocket1_NewConnection (Successful As Boolean, NewSocket As Socket) 
If Successful Then   
   Socket1 = NewSocket   
   Timer1.Enabled = True  
   InputStream1 = Socket1.InputStream  
   OutputStream1 = Socket1.OutputStream   
   Log("forbindet")
Else     
   Msgbox(LastException.Message, "Error connecting")  
End If  
ServerSocket1.Listen 'Continue listening to new incoming connections
End Sub



Sub Timer1_Tick
Dim BC As ByteConverter   
Dim data As String
If InputStream1.BytesAvailable > 0 Then   
   Timer1.Enabled = False         
   Dim buffer(8192) As Byte      
   InputStream1.ReadBytes(buffer, 0, buffer.Length)    
   data=BC.StringFromBytes(buffer,"UTF-8")
   Dim komando, param As String
   Dim sep1 As Int ' index of separators
   sep1 = data.IndexOf("|")
   komando = data.SubString2(0, sep1)
   param = data.SubString(sep1 + 1)
   Log("komando: " & komando & " --- " & "param: " & param)
   data_input(komando, param)
   Timer1.Enabled = True  
End If
End Sub
Vb.net client:
B4X:
Imports System.Net
Imports System.Net.Sockets
Public Class Form1
    Dim ip As IPAddress 
    Dim port As Integer 
    Dim sock_1, sock_2, sock_3 As New TcpClient()

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        ip = IPAddress.Parse(TextBox_ip.Text)
        port = TextBox_Port.Text
        sock_1.Connect(ip, port)
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        sock_1.Client.Send(System.Text.Encoding.UTF8.GetBytes(TextBox1.Text))
    End Sub


    Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        sock_1.Close()
    End Sub


    Public Sub kom_terminal_1(ByVal komando As String, ByVal param As String)

        If sock_1.Connected = False Then sock_1.Connect(IPAddress.Parse("192.168.0.6"), 2222)
        sock_1.Client.Send(System.Text.Encoding.UTF8.GetBytes(komando & "|" & param))

    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Call kom_terminal_1("21", "det er bare en test")
    End Sub


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub
End Class
Is that an okay/smart solution – or is there at better way ?
How do the server look up the IP-address of the client ?
********* --------------------------- **********

Android -> PC.

vb.net:
B4X:
Imports System.Net
Imports System.Text
Imports System.Net.Sockets
Public Class Form1
    Const ipAddress As String = "127.0.0.1"
    Const portNumber As Integer = 8000
    Dim tcpListener As New TcpListener(portNumber)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
           tcpListener.Start()       
Debug.Print("Waiting for connection...")
           Try            'Accept the pending client connection and return             'a TcpClient initialized for communication.       

            Dim tcpClient As TcpClient = tcpListener.AcceptTcpClient()
            Debug.Print("Connection accepted.")                                     ' Get the stream      
            Dim networkStream As NetworkStream = tcpClient.GetStream()              ' Read the stream into a byte array       
            Dim bytes(tcpClient.ReceiveBufferSize) As Byte
            networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))         ' Return the data received from the client to the console.   
            Dim clientdata As String = Encoding.ASCII.GetString(bytes)
            Debug.Print(("Modtaget: " + clientdata))

            Dim responseString As String = "Tak for data(fra vb.net)"
            Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(responseString)
            networkStream.Write(sendBytes, 0, sendBytes.Length)

            Debug.Print(("Send: " + responseString))            'Any communication with the remote client using the TcpClient can go here.          
            tcpClient.Close() 'Close TcpListener and TcpClient.     
            tcpListener.Stop()
            Debug.Print("stoppet igen")

        Catch ex As Exception
            Debug.Print(e.ToString())
        End Try
    End Sub


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

End Class

Andorid:
B4X:
'Activity module
Sub Process_Globals    
   Dim AStreams As AsyncStreams   
   Dim Server As ServerSocket  
   Dim Socket1 As Socket
   Dim forbindelse As Int
End Sub

Sub Globals  
   Dim EditText1 As EditText  
   Dim lbStatus, lbResult As Label
   Dim tw As TextWriter
   Dim tr As TextReader 
   Dim sb As StringBuilder 
End Sub
Sub Activity_Create(FirstTime As Boolean)  
   Activity.LoadLayout("1")    
   Socket1.Initialize("Socket1")
End Sub

'Sub EditText1_EnterPressed    
'If AStreams.IsInitialized = False Then Return    
'If EditText1.Text.Length > 0 Then      
'   Dim buffer() As Byte       
'   buffer = EditText1.Text.GetBytes("UTF8")    
'   AStreams.Write(buffer)     
'   EditText1.SelectAll      
'   Log("Sending: " & EditText1.Text)    
'End If
'End Sub

Sub Activity_Pause(UserClosed As Boolean)  
If UserClosed Then     
   'AStreams.Close      
   Socket1.Close  
End If
End Sub
Sub btnConnect_Click  
 Try   
If Socket1.Connected=False Then Socket1.Connect("192.168.0.7" , 8000, 20000)     'Socket1.Connect("95.166.205.135" , 5100, 20000)  
Catch    
ChangeStatus("fail")  
End Try   
End Sub

Sub btnDisconnect_Click
'AStreams.Close
tr.Close
tw.Close
Socket1.Close()
ChangeStatus("disconnect")
End Sub

Sub ChangeStatus(thetype As String)
If(thetype = "connect") Then
   Log("Connected to Server!")
Else If(thetype = "disconnect") Then
   Log( "Disconnected")
Else If(thetype = "fail") Then
   Log( "Unable to connect to Server!")
End If
End Sub


Sub Socket1_Connected (Successful As Boolean)  
    If Successful = False Then  
        Msgbox(LastException.Message, "Error connecting")  
        forbindelse=0
      Return  
    End If  
   ChangeStatus("connect") 
      
    tr.Initialize(Socket1.InputStream) 
    tw.Initialize(Socket1.OutputStream) 
   Dim data As String
   data="så kom der hul igennem - besked fra android 1"
    tw.WriteLine(data) 
    Log("Har Send: " & data)
    tw.Flush     
    
   sb.Initialize 
    sb.Append(tr.ReadLine)  
    Log("modtaget " & sb.ToString )
   ' Socket1.close

End Sub

Sub send_data(data As String)
   tr.Initialize(Socket1.InputStream) 
    tw.Initialize(Socket1.OutputStream) 
    Dim data As String
   If data="" Then data="send via send_data funk"
   tw.WriteLine(data) 
    Log("Har sendt2: " & data)
    tw.Flush     
   
   sb.Initialize 
    sb.Append(tr.ReadLine)  
    Log("modtaget2 " & sb.ToString )
   
End Sub

Sub Button1_Click
If Socket1.Connected=False Then Socket1.Connect("192.168.0.7" , 8000, 20000)     

   send_data("test")
End Sub
It works for only one connection, and I cannot make a new connection before the programs I restarted.

Is it the correct/best way ? – how do I fix to work “all the time” ? (Does any one have a working example?)

If it is enough with one of the devices to act as server – then the PC/vb.net is the preferred.

Thanks in advance

Kent
 
Last edited:

kent

Member
Licensed User
Longtime User
Thanks for your response – I really need it since I´m new to android and basic4android !

I don´t like the idea with using your B4AServer, because the vb.net server part will be a part of a larger application, and needed to be as fast as possible. (It is for a home automation system – and you don’t want to wait to long for the light to turn on etc.)

I don´t believe it is a firewall issue – since it works partly (the 1. Time) (but I will try to disable it)

I have tried with two new vb.net server socket parts: (now they listen all the time)

1) Synchronous
B4X:
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports Microsoft.VisualBasic
Public Class Form1
    Public Shared data As String = Nothing  ' Incoming data from the client.
   

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim bytes() As Byte = New [Byte](1024) {}  ' Data buffer for incoming data.

        ' Establish the local endpoint for the socket.
        ' Dns.GetHostName returns the name of the host running the application.
        Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
        Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
        Dim localEndPoint As New IPEndPoint(ipAddress, 8000)

        Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ' Create a TCP/IP socket.

        ' Bind the socket to the local endpoint and listen for incoming connections.
        listener.Bind(localEndPoint)
        listener.Listen(10)

        While True ' Start listening for connections.
            Debug.Print("Venter på fopbindelse...")
            ' Program is suspended while waiting for an incoming connection.
            Dim handler As Socket = listener.Accept()
            data = Nothing

            While True ' An incoming connection needs to be processed.
                bytes = New Byte(1024) {}
                Dim bytesRec As Integer = handler.Receive(bytes)
                data += Encoding.ASCII.GetString(bytes, 0, bytesRec)
                Debug.Print("Rådata: " & data)
                If data.IndexOf("<EOF>") > -1 Then
                    Exit While
                End If
            End While
            ' Show the data on the console.
            Debug.Print("Modtaget : {0}", data)
            ' Echo the data back to the client.
            Dim msg As Byte() = Encoding.ASCII.GetBytes(data)
            handler.Send(msg)
            handler.Shutdown(SocketShutdown.Both)
            handler.Close()
        End While

    End Sub

  
End Class
1) Asynchronous
B4X:
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Imports Microsoft.VisualBasic

Public Class Form1
    Public Shared allDone As New ManualResetEvent(False) ' Thread signal.
    Public Class StateObject
        Public workSocket As Socket = Nothing       ' Client  socket.
        Public Const BufferSize As Integer = 1024   ' Size of receive buffer.
        Public buffer(BufferSize) As Byte           ' Receive buffer.
        Public sb As New StringBuilder              ' Received data string.
    End Class 'StateObject
    Public Shared Sub AcceptCallback(ByVal ar As IAsyncResult)
        Dim listener As Socket = CType(ar.AsyncState, Socket)   ' Get the socket that handles the client request.
        Dim handler As Socket = listener.EndAccept(ar)          ' End the operation.
        Dim state As New StateObject                            ' Create the state object for the async receive.
        state.workSocket = handler
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
    End Sub 'AcceptCallback

    Public Shared Sub ReadCallback(ByVal ar As IAsyncResult)
        Dim content As String = String.Empty
        ' Retrieve the state object and the handler socket from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim handler As Socket = state.workSocket
        ' Read data from the client socket. 
        Dim bytesRead As Integer = handler.EndReceive(ar)
        If bytesRead > 0 Then
            ' There  might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))
            ' Check for end-of-file tag. If it is not there, read more data.
            content = state.sb.ToString()
            If content.IndexOf("<EOF>") > -1 Then   ' All the data has been read from the client. Display it on the console.
                Debug.Print("Read {0} bytes from socket. " + vbLf + " Data modtaget : {1}", content.Length, content)
                Send(handler, content)              ' Echo the data back to the client.
            Else                                    ' Not all data received. Get more.
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
            End If
        End If
    End Sub 'ReadCallback

    Private Shared Sub Send(ByVal handler As Socket, ByVal data As String)
        Dim byteData As Byte() = Encoding.ASCII.GetBytes(data)  ' Convert the string data to byte data using ASCII encoding.
        handler.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), handler)  ' Begin sending the data to the remote device.
        Debug.Print("Sendt til klilent: " & data)
    End Sub 'Send
    Private Shared Sub SendCallback(ByVal ar As IAsyncResult)
        Dim handler As Socket = CType(ar.AsyncState, Socket) ' Retrieve the socket from the state object.
        ' Complete sending the data to the remote device.
        Dim bytesSent As Integer = handler.EndSend(ar)
        Debug.Print("Sent {0} bytes to client.", bytesSent)
        handler.Shutdown(SocketShutdown.Both)
        handler.Close()
        allDone.Set() ' Signal the main thread to continue.
    End Sub 'SendCallback

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim bytes() As Byte = New [Byte](1023) {} ' Data buffer for incoming data.
        ' Establish the local endpoint for the socket.
        Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
        Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
        Dim localEndPoint As New IPEndPoint(ipAddress, 8000)

        Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ' Create a TCP/IP socket.

        ' Bind the socket to the local endpoint and listen for incoming connections.
        listener.Bind(localEndPoint)
        listener.Listen(100)
        While True
            allDone.Reset()   ' Set the event to nonsignaled state.
            ' Start an asynchronous socket to listen for connections.
            Debug.Print("Venter på forbindelse...")
            listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)
            allDone.WaitOne()   ' Wait until a connection is made and processed before continuing.
        End While
    End Sub
End Class

But I still have (at least) two problems.

1) The Vb.net program seems to stall/suspend while waiting for a connecting client, both in vb.net server part 1 and part 2 – I suppose the idea with the ASynchronous part (2) was to avoid that !
Is it better to use the tcp-listener instead for “socket-listener” ?

2) I can only connect once with the android code – but with my vb.net test application I can connect as many times as I like. What is wrong with my android code ?

The second time “Socket1_Connected” is raised the "Connected" Is false !

When is the right time to close the socket ?

My android code looks like: (it is the same problem with both versions)

B4X:
'Activity module
Sub Process_Globals    
   Dim AStreams As AsyncStreams   
   Dim Server As ServerSocket  
   Dim Socket1 As Socket
End Sub

Sub Globals  
End Sub
Sub Activity_Create(FirstTime As Boolean)  
   Activity.LoadLayout("1")    
   Socket1.Initialize("Socket1")
End Sub

Sub Activity_Pause(UserClosed As Boolean)  
If UserClosed Then     
   Log("closing")     
   'AStreams.Close      
   'Socket1.Close  
End If
End Sub
Sub btnConnect_Click  
Try   
Socket1.Connect("192.168.0.7" , 8000, 20000)    
Catch    
Log("fejlede") 
End Try   
End Sub
Sub btnDisconnect_Click
Log("prøver at afbryde")
AStreams.Close
Socket1.Close()
End Sub

Sub Socket1_Connected (Connected  As Boolean)  
   If Connected = True Then   
       Log("forbindelse")     
         AStreams.Initialize(Socket1.InputStream,Socket1.OutputStream,"Astreams")  
    Dim data As String
    Dim buffer() As Byte 
    data="opretter forbindelse"
    data=data & "<EOF>"
   buffer = data.GetBytes("UTF8")    
   AStreams.Write(buffer) 
   Log("Har send: " & data)
   'Socket1.close
    Else   
      Log("forbindelse fejl")  
    End If
   

End Sub

Sub send_data(data As String)
Log("asynkron status: " & AStreams.IsInitialized)
If AStreams.IsInitialized = True Then   
   Log("i asynkron send funktion 222")
   Dim buffer() As Byte       
   If data="" Then data="send via send_data funk"
      data=data & "<EOF>"
      buffer = data.GetBytes("UTF8")    
      AStreams.Write(buffer)     
End If
End Sub

Sub Button1_Click
   'If Socket1.Connected=False Then Socket1.Connect("192.168.0.7" , 8000, 20000)    
   send_data("test")
End Sub
Sub AStreams_NewData (Buffer() As Byte)
Dim msg As String  
msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8") 
Log("asynkron data modtaget: " & msg)
End Sub
Sub AStreams_Error   
Log(LastException.Message)
End Sub
And
B4X:
'Activity module
Sub Process_Globals    
   Dim Server As ServerSocket  
   Dim Socket1 As Socket
End Sub

Sub Globals  
   Dim tw As TextWriter
   Dim tr As TextReader 
   Dim sb As StringBuilder 
End Sub
Sub Activity_Create(FirstTime As Boolean)  
   Activity.LoadLayout("1")    
   Socket1.Initialize("Socket1")
End Sub

Sub Activity_Pause(UserClosed As Boolean)  
If UserClosed Then     
   Log("closing")     
   Socket1.Close  
End If
End Sub
Sub btnConnect_Click  
Log("prøver at forbinde")
 Try   
Socket1.Connect("192.168.0.7" , 8000, 20000)     'Socket1.Connect("95.166.205.135" , 5100, 20000)  
Catch    
ChangeStatus("fail")  
End Try   
End Sub
Sub btnDisconnect_Click
Log("prøver at afbryde")
tr.Close
tw.Close
Socket1.Close()
ChangeStatus("disconnect")
End Sub
Sub ChangeStatus(thetype As String)
If(thetype = "connect") Then
   Log("Connected to Server!")
Else If(thetype = "disconnect") Then
   Log( "Disconnected")
Else If(thetype = "fail") Then
   Log( "Unable to connect to Server!")
End If
End Sub


Sub Socket1_Connected (Successful As Boolean)  
    If Successful = False Then  
        Log(LastException.Message)
      Return  
    End If  
   ChangeStatus("connect") 
    tr.Initialize(Socket1.InputStream) 
    tw.Initialize(Socket1.OutputStream) 
   Dim data As String
   data="så kom der hul igennem - besked fra android 1"
   data=data & "<EOF>"
    tw.WriteLine(data) 
    Log("Har Send: " & data)
    tw.Flush     
   sb.Initialize 
    sb.Append(tr.ReadLine)  
    Log("modtaget " & sb.ToString )
   ' Socket1.close
End Sub

Thanks in advance .
Kent
 
Upvote 0

geBeppe

New Member
Help!

I have a problem with my android client.
I use this code:

Socket1.Initialize("Socket1")
Socket1.Connect("192.168.0.245",20001,20000)

I tried to connect my tablet connected with wifi to a vb6 server.
What is the problem??

Thanks
 
Upvote 0
Top