B4J Question ServerSocket and Socket

Aristide

Member
Code give by Erel

B4X:
Sub Process_Globals
   Private server As ServerSocket
   Private astream As AsyncStreams
End Sub

Sub AppStart (Args() As String)
   server.Initialize(51042, "server")
   server.Listen
   StartMessageLoop
End Sub

Sub server_NewConnection (Successful As Boolean, NewSocket As Socket)
   Log("New connection")
   If Successful Then
     astream.Initialize(NewSocket.InputStream, NewSocket.OutputStream, "astream")
   End If
   server.Listen
End Sub

Sub astream_NewData (Buffer() As Byte)
   Log(BytesToString(Buffer, 0, Buffer.Length, "utf8"))
   astream.Write("received!".GetBytes("utf8"))
End Sub

Hello,
I use this "same" code for the "link" to an application (Scratch) that sends bursts of "GET / POLL". I get the first "get / poll" with "keep alive" in the HTTP header for the connection. With "serversocket" object, I get an error "connection reset"

I made the same program with "socket" object, I only have one client, i get another error "read time-out"

It seem's that the event "newdata" of the stream only goes back one request.

Thank you for your help.

With serversocket

...
New connection
GET /poll HTTP/1.1
Referer: app:/Scratch.swf
Accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, text/css, image/png, image/jpeg, image/gif;q=0.8, application/x-shockwave-flash, video/mp4;q=0.9, flv-application/octet-stream;q=0.8, video/x-flv;q=0.7, audio/mp4, application/futuresplash, */*;q=0.5, application/x-mpegURL
x-flash-version: 24,0,0,174
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (Windows; U; fr-FR) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/24.0
Host: 127.0.0.1:12345
Connection: Keep-Alive
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:188)
at java.lang.Thread.run(Thread.java:745)

New connection
GET /poll HTTP/1.1
Referer: app:/Scratch.swf
Accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8, text/css, image/png, image/jpeg, image/gif;q=0.8, application/x-shockwave-flash, video/mp4;q=0.9, flv-application/octet-stream;q=0.8, video/x-flv;q=0.7, audio/mp4, application/futuresplash, */*;q=0.5, application/x-mpegURL
x-flash-version: 24,0,0,174
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (Windows; U; fr-FR) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/24.0
Host: 127.0.0.1:12345
Connection: Keep-Alive
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
It seem's that the event "newdata" of the stream only goes back one request.
No. The NewData will be raised whenever there is data available. Connection reset means that the client closed the connection.

You need to handle the Terminated and Error events as well to manage the connection.

I recommend you to use jServer if you want to implement a http server.
 
Upvote 0

Aristide

Member
Thank you for that answer. But I already implement Jserver, that's ok, but it's "crush a fly with a hammer" : "écraser une mouche avec un marteau" en français. Jetty and your implementation is very good, but I need a very light implementation. A client, Scratch is an application of a single instance and very "rustic".

In the current version with Jserver, I receive a burst of / poll by sucucessives commands "Get /poll". At the rate of 30 per second !!! Not really effective as a solution, but it was the Scratch team that decided it.

My aim is to try to improve the performance by limiting the weight of the code to manage the HTTP protocol between the Scratch client and my version, not to analyze the header, etc. mono instance, .... as Jserver does . There is also a "function" that I can not remove in Jetty. It produces a log of the requests with these / poll in mass, the file grows without limit, finally ... it is not the essential reason of my objective, I automatically clean but ...

As for the newdata on the astream of the socket (or serversocket) it is the same. In the case of the socket, I see a "read timeout" in the case of "serversocket" as I showed a disconnection and a single request that arrives.

A Get Http requires an answer, I sent an OK 200, it did nothing.

Thank you all for your reply. If you have a track or a idea ...

I will try to replicate the case with a small client that bombards your HTTP request program to see why it does not work.
 
Upvote 0

Aristide

Member
You are right. It is a TRUE HTTP server. It's not about questioning the quality of Jetty, its power, its ability to scale up, accept multiple queries ...

I tested the Jserver throughput in my case. The Scratch rate is about 30 requests per second.

With a minimum server,( see code) I manage to assume this debit, no spot if it is to calculate and make time takes.

In the case of my application, I find a rate of half, it is true that the code executed from a query received is heavier, but of little. I put the queries in a list that is consumed by a stand-alone process.

I just wanted to test to see if the Jetty load, released by the implementation of a simple server, could be recovered to the benefit of the debit. This is a test that costs me very little.

It is for this reason that I would like to know why I can recover only ONE request.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Public srvr As Server
    Public NbPoll As Long
    Public debTemps As Long
    Public receive As Receivereq
End Sub

Sub AppStart (Args() As String)
    receive.Initialize
    srvr.Initialize("srvr")
    srvr.AddHandler("/*", "Receivereq",False)
    srvr.Port = 12345
    srvr.DebugNetworkLatency = 0
    srvr.Start
    StartMessageLoop
End Sub

and

B4X:
'Handler class
Sub Class_Globals
    Private list As List
    Private JS As JStringFunctions
   
End Sub

Public Sub Initialize
    JS.Initialize
End Sub

Sub Handle(req As ServletRequest, resp As ServletResponse)
   
    list.Initialize
    list= JS.split(req.RequestURI,"/")
    Select list.Get(1)
        Case "poll"
                Main.NbPoll = Main.NbPoll + 1
                If Main.NbPoll = 1 Then Main.debTemps = DateTime.Now
                If DateTime.Now - Main.debTemps > 1000 Then
                    Log("Debit : " & Main.NbPoll & " à la seconde")
                    Main.NbPoll = 0
                End If
    End Select
   
End Sub
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
As I previously wrote, 30 requests per second is not considered high rate. A regular PC should be able to handle 1000+ requests per second assuming that requests are not too heavy.

Anyway, you can choose whichever implementation you like.

Question:
It seem's that the event "newdata" of the stream only goes back one request.
Answer:
No. It is raised whenever there is data available. You need to find out why the client closed the connection.
 
Upvote 0

Aristide

Member
Thank you for all those informations. I knew this was an HTTP problem but I did not understand why HTTP 200 OK did not work.

Eureka !!! It was simply a confusion caused by the term "CRLF" which is only the hexa 0A character, HTTP protocol want "0A0D". So I added to the HTTP string in response to the get a response of length 0 with 200 OK and the correct separators "0A0D".

This works flawlessly.

PS: I think I misunderstood. I do not in any way question the ability of Jetty to bear the burden of the 30 reqests/second. I simply pointed out that the Jetty solution is much more "powerful" and that a minimal implementation was sufficient for the "rustic" link with Scracth.

PS2 : The response


B4X:
Private OAOD As String = Chr(13) & Chr(10)
Private rep As String = "HTTP/1.1 200 OK" & OAOD  & "Content-Length: 0" & OAOD & OAOD
 
Last edited:
Upvote 0
Top