Keenan Gebze Keenan Gebze - 1 month ago 10
Java Question

How to implements Simple SSE Server using Java?

I want to implement Server Sent Events (SSE) using simple Java Server Socket (instead with php and/or asp).

This server will do only simple things: listening for incoming request from browser, creates a handler thread, reply the request (sending header) without closing the connection, and then, wait for user input (System.in) that will forward the messages to the client.

Of course it will be an overkill if I use J2EE library (eg. Jersey) just for doing task like that.

The source is as follow:

import java.net.*;
import java.io.*;
import java.util.Scanner;

public class Loc {
public static void main ( String[] args ) throws IOException{
ServerSocket ss = new ServerSocket(8888);
//listen to only one connection.
System.out.print("Waiting for connection...");

Socket hp = ss.accept();
System.out.println("Connected!");


BufferedReader br = new BufferedReader(new InputStreamReader(hp.getInputStream()));

String line = "";
while( br.ready() && (line=br.readLine()) != null) { //dumps request header.
System.out.println(line);
}

Thread handler = new Thread(new ClientHandler(hp));
handler.start();
try {
handler.join();
}catch(InterruptedException e){

}
System.out.println("Server stopped.");
}
}

class ClientHandler implements Runnable{

Socket toClient;

public ClientHandler(Socket s){
this.toClient = s;
}

public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //server input (also forwards it to client)
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(toClient.getOutputStream()));

// response header.
String response = "HTTP/1.1 200 OK\n"+
"Server: Maknyos-Server/1.0\n"+
"Cache-Control: no-cache,public\n"+
"Content-Type: text/event-stream\n"+
"Connection: keep-alive\n"+
"Language: en-US\n"+
"Charset: UTF-8\n"+
"\n"; //two line break as header ending.

bw.write(response);
bw.flush();

String input = "";
while ( (input = br.readLine()) != null ) { //one directional message to client (browser), via cmd.

bw.write(input+'\n');
bw.flush();
if("close".equalsIgnoreCase(input)){
break;
}
}

toClient.close();
}catch(IOException e){
System.out.println("IOEXception! "+e);
}
}


This is the client.

<h1>Hullo World!</h1>
<script type="text/javascript">

var es = new EventSource("http://localhost:8888");
es.onmessage = function (event) {
alert(event.data);
};
</script>


When I open the html page, I can see the http request header on my server std out (command line).
My server then reply it with

HTTP/1.1 200 OK
Server: Maknyos-Server/1.0
Cache-Control: no-cache,public
Content-Type: text/event-stream
Connection: keep-alive
Language: en-US
Charset: UTF-8


...


I'll try to describe what I do and what is the problems, between those two client and server. It maybe related to the protocol, but I'm not sure.

First, If I put only two (new line) at the end of the header to finish the response header (as the example above), Firefox console will tell me that the browser can't connect to the server. But, in the NET console, it receives the response request.

Second, I test without finishing the response header (without double \n character).

Neither of them succeeded in sending SSE to the browser.

Edit, when I see again the browser's console windows, it appears that It cannot make a request to another domain!

this program runs on localhost:8888
but the webserver I use (for the html page) is on localhost:80

Answer

It turns out that I'm missing one important header in my server header string.

"Access-Control-Allow-Origin:*" + "\r\n" + ...