Android Question [RESOLVED] Socket.close

Jmu5667

Well-Known Member
Licensed User
Longtime User
Hi

I have a socket class which get created in a service. After I have done my business sending data tot he Server (VB6 Winsock), and I call classname.ws_close from within the service, the socket is not terminated on the server side.

I tested this with an sample program someone else had written and their socket was in the main activity and it closed it connect correctly, that is the server picked up the disconnect.

Any idea's anyone ?

Regards

John.
 

Jmu5667

Well-Known Member
Licensed User
Longtime User
Make sure that you are not creating multiple sockets. Closing an active socket will break the connection. It might be better to first send a "close" command to the server and then close the connection.
Hi Erel

Thanks for the reply. I implemented a close command that is sent to the server. There is only one connection made to the server. I will check to see if I cam creating multiple instances of the class, as far I can see there is only one. Is is possible that it because it is created off the main GUI thread ?

Regards

John.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Make sure that you are not creating multiple sockets. Closing an active socket will break the connection. It might be better to first send a "close" command to the server and then close the connection.
Just checked and only one instance is being created.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Are you using the Threading library?
Nope, just a class for the socket, and a service that makes an instance of the class. Everything is working perfectly except the close bit. As I mentioned earlier I test the socket in an activity and does the close correctly.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Yep, using async steams, and closing them. Heres the class, it pretty small and simple.

B4X:
'Class module
Sub Class_Globals
   
   Private callback As Object
   Private event As String
   
   Dim WS_SOCKET As Socket
   Dim WS_IO_ASTREAM As AsyncStreams
   
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(callBackModule As Object,callBackEvent As String)
   
   callback = callBackModule
   event = callBackEvent

   WS_SOCKET.Initialize("ws_socket")

End Sub
Sub ws_socket_Connected(Connected As Boolean)As Boolean
   
   
   Try
     If Connected = True Then
       If Not(WS_IO_ASTREAM.IsInitialized ) Then
         WS_IO_ASTREAM.Initialize(WS_SOCKET.InputStream,WS_SOCKET.OutputStream,"wsStream")
       End If
     Else
       
       If SubExists(callback, event & "_failure") Then
         CallSub2(callback, event & "_failure",LastException.Message)
       End If
     End If
     If SubExists(callback, event & "_Connected") Then
       CallSub2(callback, event & "_Connected",Connected)
     End If
   Catch
     
     If SubExists(callback, event & "_socket_failure") Then
       CallSub2(callback, event & "_failure",LastException.Message)
     End If
   End Try

   Return Connected
   
End Sub

Sub wsStream_NewData (Buffer() As Byte)
   
   Dim wsData As String
   
   wsData = BytesToString(Buffer, 0, Buffer.Length, "ASCII")
   If SubExists(callback, event & "_DataArrival") Then
     CallSub2(callback, event & "_DataArrival",wsData)
   End If

End Sub

Sub wsStream_Terminated()
   
   ws_close
   
End Sub
Sub  wsStream_Error

   If SubExists(callback, event & "_StreamError") Then
     CallSub2(callback, event & "_StreamError", LastException.Message)
   End If
   
End Sub
Sub ws_connect(pHost As String, pPort As Int, pTimeout As Int)
   
   If Not(WS_SOCKET.IsInitialized) Then
     WS_SOCKET.Initialize("ws_socket")
   End If
   WS_SOCKET.Connect(pHost,pPort,pTimeout)

End Sub
Sub ws_close()
   
   
   'If WS_SOCKET.Connected Then
     WS_IO_ASTREAM.Close
     WS_SOCKET.Close
   'End If
   
   If SubExists(callback, event & "_closed") Then
     CallSub(callback, event & "_closed")
   End If


End Sub

Sub ws_isConnected() As Boolean
   
   Return WS_SOCKET.Connected  

End Sub

Sub ws_isInitialised() As Boolean
   
   Return WS_SOCKET.IsInitialized   

End Sub

Sub ws_senddata(pData As String)

   Dim Buffer() As Byte
   
   If Not(ws_isConnected) Then
     Log(DateTime.Time(DateTime.Now) & " - ws_senddata() No connection ")
     Return
   End If
   
   Try
     
     If Not(WS_IO_ASTREAM.IsInitialized) Then
       WS_IO_ASTREAM.Initialize(WS_SOCKET.InputStream,WS_SOCKET.OutputStream,"wsStream")
     End If
     
     ' // wrap the packet
     pData = Main.tx.stx & pData & Main.tx.eot
     ' // load byte array
     Buffer = pData.GetBytes("UTF8")
     If Not(WS_IO_ASTREAM.Write(Buffer)) Then
       If SubExists(callback, event & "_failure") Then
         CallSub2(callback, event & "_failure",LastException.Message)
       End If
     End If
   Catch
     ' // reset the connection
     If SubExists(callback, event & "_StreamError") Then
       CallSub2(callback, event & "_StreamError", "ws_senddata() " &  LastException.Message)
     End If
   End Try
   
   
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Note that you do not need to check that the subs exist before "raising an event" with CallSub.

Have you encountered a case where WS_IO_ASTREAM is not initialized in ws_senddata? This code looks fragile. If it is not initialized then you shouldn't initialize it at that point.
Call ws_close from wsStream_Error as well.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Note that you do not need to check that the subs exist before "raising an event" with CallSub.

Have you encountered a case where WS_IO_ASTREAM is not initialized in ws_senddata? This code looks fragile. If it is not initialized then you shouldn't initialize it at that point.
Call ws_close from wsStream_Error as well.


Thanks, I'll make the necessary changes. And let you know how it goes.
 
Upvote 0

Jmu5667

Well-Known Member
Licensed User
Longtime User
Note that you do not need to check that the subs exist before "raising an event" with CallSub.

Have you encountered a case where WS_IO_ASTREAM is not initialized in ws_senddata? This code looks fragile. If it is not initialized then you shouldn't initialize it at that point.
Call ws_close from wsStream_Error as well.

Ah well, sorted !!! thanks Erel.
 
Upvote 0

cbal03

Member
Licensed User
Longtime User
I found that when closing a socket via wsh.ws.Close I get an error:
Connection Lost: WebSockets internal error (java.nio.channels.ClosedChannelException)

And periodically, 7 of 10 times, this will actually crash the websocket server with an error 'An established connection was abandoned by the software in your host machine.' I should probably be sending a 'close' or 'disconnect' to the server and let the server close the connection but websockets describes the client as maintaining the connection which means the client should be able to just disappear, correct?.

The socket is initialized using wsh.Initialize(Me, "wsh") because the isinitialized method is only available in wsh and I use that to detect if it has already been initialized before attempting to connect..

How should initialization and closing be used?
I can do any of the following but this is confusing.

dim wsh as websockethandler
wsh.Initialize(Me, "wsh")
wsh.Close
wsh.Connect
wsh.Initialize
wsh.IsInitialized
wsh.SendEventToServer

OR

dim wsh as websockethandler
wsh.ws.Close
wsh.ws.Connect
wsh.ws.Connected
wsh.ws.Initialize(eventname as string)
wsh.ws.SendText

Which methods should I be using when establishing a connection and what's the difference between them?
I searched for hours but didn't find answers to my questions.

Thanks
 
Upvote 0
Top