Using html5 client with server in java

The HTML5 client reduces programmer performance by providing the client with the html5 websocket client. It will be useful for many programmers to learn how to use this html5 websocket client with a server in java.

I want to create an example HTML5 client interacting with a java server, but I cannot find out how to do this. can anyone shed light on him?

Link: demo html5 client / server with C ++

I found a demo at http://java.dzone.com/articles/creating-websocket-chat , but it does not work for me ..

+8
java html5 webserver websocket client
source share
6 answers

I have implemented a simple Java server side example that we can take a look at. I start by creating a ServerSocket that listens for connection to port 2005

public class WebsocketServer { public static final int MASK_SIZE = 4; public static final int SINGLE_FRAME_UNMASKED = 0x81; private ServerSocket serverSocket; private Socket socket; public WebsocketServer() throws IOException { serverSocket = new ServerSocket(2005); connect(); } private void connect() throws IOException { System.out.println("Listening"); socket = serverSocket.accept(); System.out.println("Got connection"); if(handshake()) { listenerThread(); } } 

As defined in the RFC standard for the websocket protocol , when a client connects through a website, a handshake must be performed. So let's take a look at the handshake () method, it's pretty ugly, so it will step through it: The first part reads a client handshake.

 private boolean handshake() throws IOException { PrintWriter out = new PrintWriter(socket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //This hashmap will be used to store the information given to the server in the handshake HashMap<String, String> keys = new HashMap<>(); String str; //Reading client handshake, handshake ends with CRLF which is again specified in the RFC, so we keep on reading until we hit ""... while (!(str = in.readLine()).equals("")) { //Split the string and store it in our hashmap String[] s = str.split(": "); System.out.println(str); if (s.length == 2) { keys.put(s[0], s[1]); } } 

The client handshake looks something like this (this is what chrome gave me, version 22.0.1229.94 m), in accordance with RFC 1.2!

 GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: localhost:2005 Origin: null Sec-WebSocket-Key: PyvrecP0EoFwVnHwC72ecA== Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: x-webkit-deflate-frame 

Now we can use the key card to create the appropriate response during the handshake. Quote from the RFC:

To confirm that a handshake has been received, the server must accept two pieces of information and combine them to form a response. The first piece of information comes from | Sec-WebSocket-Key | header field in client handshake. For this header field, the server must take a value and combine this with a globally unique identifier, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" as a string that is unlikely to be used by network endpoints that do not understand the WebSocket Protocol. The SHA-1 hash (160 bits), base64 encoded, this concatenation is then returned in the server acknowledgment.

So what should we do! Sec-WebSocket-Key concatenation with magic string, hash using the SHA-1 hash function and Base64-encode. This is what the next ugly single-liner does.

 String hash; try { hash = new BASE64Encoder().encode(MessageDigest.getInstance("SHA-1").digest((keys.get("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes())); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); return false; } 

Then we simply return the expected response with a new hash created in the "Sec-WebSocket-Accept" field.

  //Write handshake response out.write("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + hash + "\r\n" + "\r\n"); out.flush(); return true; 

}

Now we have established a successful connection to the server between the client and server. And now what? How do we make them talk to each other? We can start by sending messages from the server to the client. NB! We are doing from now on, and not talking to the client with HTTP anymore. Now we have to report sending pure bytes and interpret incoming bytes. So how do we do this?

The message from the server must be in a specific format called "frames", as described in RFC 5.6. When sending a message from the server, the RFC states that the first byte should indicate what it is. A byte with a value of 0x81 tells the client that we are sending a "single-frame unmasked text message", which is basically a text message. The subsequent byte should represent the length of the message. After that, data or payload. Well, okay ... let this be realized!

 public void sendMessage(byte[] msg) throws IOException { System.out.println("Sending to client"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream()); //first byte is kind of frame baos.write(SINGLE_FRAME_UNMASKED); //Next byte is length of payload baos.write(msg.length); //Then goes the message baos.write(msg); baos.flush(); baos.close(); //This function only prints the byte representation of the frame in hex to console convertAndPrint(baos.toByteArray()); //Send the frame to the client os.write(baos.toByteArray(), 0, baos.size()); os.flush(); } 

So, to send a message to the client, we simply call sendMessage ("Hello, client!". GetBytes ()).

Wasn't that too complicated? How to receive messages from a client? Well, it's a little trickier, but hang in there!

The sendt frame from the client is almost structured like the frame sendt from the server. The first byte is the type of message, and the second byte is the length of the payload. Then there is a difference: the next four bytes are a mask. What mask, and why messages from the client are masked, but there are no messages with the servers? Section 5.1 of the RFC shows that:

... the client SHOULD mask all the frames that it sends to the server ... The server SHOULD not mask any frames that it sends to the client.

So the easy answer is: we just HAVE. Well, why should we, you may ask? Didn't I tell you to read the RFC?

Moving, after a four-byte mask in the frame, the oil payload is displayed. And one more thing: the client must set the 9th leftmost bit in the frame to 1 to inform the server that the message is masked (check the clean ASCII-art frame in the RFC section - section 5.2). The 9th leftmost bit corresponds to our leftmost bit in our second byte, but hey, our byte is the payload length! This means that all messages from our client will have payload length bytes equal to 0b10000000 = 0x80 + actual payload length. Therefore, in order to find out the actual payload length, we must subtract 0x80 or 128 or 0b10000000 (or any other number system you may prefer) from the payload length byte, our second byte in the frame.

Wow, okay .. that sounds complicated ... For you, "TL; DR" -guys, summary: subtract 0x80 from the second byte to get the payload length ...

 public String reiceveMessage() throws IOException { //Read the first two bytes of the message, the frame type byte - and the payload length byte byte[] buf = readBytes(2); System.out.println("Headers:"); //Print them in nice hex to console convertAndPrint(buf); //And it with 00001111 to get four lower bits only, which is the opcode int opcode = buf[0] & 0x0F; //Opcode 8 is close connection if (opcode == 8) { //Client want to close connection! System.out.println("Client closed!"); socket.close(); System.exit(0); return null; } //Else I just assume it a single framed text message (opcode 1) else { final int payloadSize = getSizeOfPayload(buf[1]); System.out.println("Payloadsize: " + payloadSize); //Read the mask, which is 4 bytes, and than the payload buf = readBytes(MASK_SIZE + payloadSize); System.out.println("Payload:"); convertAndPrint(buf); //method continues below! 

Now that we have read the entire message, it's time to expose it so that we can understand the meaning of the payload. To expose it, I created a method that takes a mask and a payload as arguments, and returns a decoded payload. Thus, the call is made using:

  buf = unMask(Arrays.copyOfRange(buf, 0, 4), Arrays.copyOfRange(buf, 4, buf.length)); String message = new String(buf); return message; } } 

Now the unMask method is pretty sweet and tiny

 private byte[] unMask(byte[] mask, byte[] data) { for (int i = 0; i < data.length; i++) { data[i] = (byte) (data[i] ^ mask[i % mask.length]); } return data; } 

The same goes for getSizeOfPayload:

 private int getSizeOfPayload(byte b) { //Must subtract 0x80 from (unsigned) masked frames return ((b & 0xFF) - 0x80); } 

It's all! You should now be able to communicate in both directions using clean sockets. I will fully add the Java class for completeness. He is able to receive and send messages with the client using web maps.

 package javaapplication5; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.HashMap; import sun.misc.BASE64Encoder; /** * * @author * Anders */ public class WebsocketServer { public static final int MASK_SIZE = 4; public static final int SINGLE_FRAME_UNMASKED = 0x81; private ServerSocket serverSocket; private Socket socket; public WebsocketServer() throws IOException { serverSocket = new ServerSocket(2005); connect(); } private void connect() throws IOException { System.out.println("Listening"); socket = serverSocket.accept(); System.out.println("Got connection"); if(handshake()) { listenerThread(); } } private boolean handshake() throws IOException { PrintWriter out = new PrintWriter(socket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); HashMap<String, String> keys = new HashMap<>(); String str; //Reading client handshake while (!(str = in.readLine()).equals("")) { String[] s = str.split(": "); System.out.println(); System.out.println(str); if (s.length == 2) { keys.put(s[0], s[1]); } } //Do what you want with the keys here, we will just use "Sec-WebSocket-Key" String hash; try { hash = new BASE64Encoder().encode(MessageDigest.getInstance("SHA-1").digest((keys.get("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes())); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); return false; } //Write handshake response out.write("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + hash + "\r\n" + "\r\n"); out.flush(); return true; } private byte[] readBytes(int numOfBytes) throws IOException { byte[] b = new byte[numOfBytes]; socket.getInputStream().read(b); return b; } public void sendMessage(byte[] msg) throws IOException { System.out.println("Sending to client"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream()); baos.write(SINGLE_FRAME_UNMASKED); baos.write(msg.length); baos.write(msg); baos.flush(); baos.close(); convertAndPrint(baos.toByteArray()); os.write(baos.toByteArray(), 0, baos.size()); os.flush(); } public void listenerThread() { Thread t = new Thread(new Runnable() { @Override public void run() { try { while (true) { System.out.println("Recieved from client: " + reiceveMessage()); } } catch (IOException ex) { ex.printStackTrace(); } } }); t.start(); } public String reiceveMessage() throws IOException { byte[] buf = readBytes(2); System.out.println("Headers:"); convertAndPrint(buf); int opcode = buf[0] & 0x0F; if (opcode == 8) { //Client want to close connection! System.out.println("Client closed!"); socket.close(); System.exit(0); return null; } else { final int payloadSize = getSizeOfPayload(buf[1]); System.out.println("Payloadsize: " + payloadSize); buf = readBytes(MASK_SIZE + payloadSize); System.out.println("Payload:"); convertAndPrint(buf); buf = unMask(Arrays.copyOfRange(buf, 0, 4), Arrays.copyOfRange(buf, 4, buf.length)); String message = new String(buf); return message; } } private int getSizeOfPayload(byte b) { //Must subtract 0x80 from masked frames return ((b & 0xFF) - 0x80); } private byte[] unMask(byte[] mask, byte[] data) { for (int i = 0; i < data.length; i++) { data[i] = (byte) (data[i] ^ mask[i % mask.length]); } return data; } private void convertAndPrint(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); } System.out.println(sb.toString()); } public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException { WebsocketServer j = new WebsocketServer(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { System.out.println("Write something to the client!"); j.sendMessage(br.readLine().getBytes()); } } } 

And a simple client in html:

 <!DOCTYPE HTML> <html> <body> <button type="button" onclick="connect();">Connect</button> <button type="button" onclick="connection.close()">Close</button> <form> <input type="text" id="msg" /> <button type="button" onclick="sayHello();">Say Hello!</button> <script> var connection; function connect() { console.log("connection"); connection = new WebSocket("ws://localhost:2005/"); // Log errors connection.onerror = function (error) { console.log('WebSocket Error '); console.log(error); }; // Log messages from the server connection.onmessage = function (e) { console.log('Server: ' + e.data); alert("Server said: " + e.data); }; connection.onopen = function (e) { console.log("Connection open..."); } connection.onclose = function (e) { console.log("Connection closed..."); } } function sayHello() { connection.send(document.getElementById("msg").value); } function close() { console.log("Closing..."); connection.close(); } </script> </body> </html> 

Hope this clarifies something, and that I shed some light on him :)

+19
source share

Use jQuery ajax requests from the client side and server-side recreation services.
Here is about creating a military module with Rest Service

Article 1 (Recreation Service)

here abour jQuery ajax

article 2 (jQuery Ajax)

To write a Java socket server, all you need to do is create the main program with

  try { final ServerSocket ss = new ServerSocket(8001); while (true) { final Socket s = ss.accept(); // @todo s.getInputStream(); } } catch (final IOException ex) { // } 

main cascade of the server part

+4
source share

Try reading this blog. It describes how to achieve your work with spring. Full support should be added soon if it is not already added.

http://keaplogik.blogspot.com.au/2012/05/atmosphere-websockets-comet-with-spring.html?m=1

I also suggest checking out the spring release notes.

+1
source share

You are using GlassFish. It does not include web sockets by default. To enable them, you must run the following single-line command in your domain:

 asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-1.http.websockets-support-enabled=true 

HttpServlet.init(...) method is called by the servlet container to indicate to the servlet that the servlet is being placed in the service. * So, your journal message there does not represent the truth.

0
source share

You can also achieve this using an existing structure, for example: jWebsocket

0
source share

This is the same code above that allows you to receive messages from the client that exceed 126 bytes. Many web socket source codes do not detect fragmentation.

  // Modified code from Anders, - Christopher Price package GoodExample; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.HashMap; import sun.misc.BASE64Encoder; public class JfragWS { public static final int MASK_SIZE = 4; public static final int SINGLE_FRAME_UNMASKED = 0x81; private ServerSocket serverSocket; private Socket socket; public JfragWS() throws IOException { serverSocket = new ServerSocket(1337); connect(); } private void connect() throws IOException { System.out.println("Listening"); socket = serverSocket.accept(); System.out.println("Got connection"); if(handshake()) { listenerThread(); } } private boolean handshake() throws IOException { PrintWriter out = new PrintWriter(socket.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); HashMap<String, String> keys = new HashMap<>(); String str; //Reading client handshake while (!(str = in.readLine()).equals("")) { String[] s = str.split(": "); System.out.println(); System.out.println(str); if (s.length == 2) { keys.put(s[0], s[1]); } } //Do what you want with the keys here, we will just use "Sec-WebSocket-Key" String hash; try { hash = new BASE64Encoder().encode(MessageDigest.getInstance("SHA-1").digest((keys.get("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes())); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); return false; } //Write handshake response out.write("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + hash + "\r\n" + "Origin: http://face2fame.com\r\n" + "\r\n"); out.flush(); return true; } private byte[] readBytes(int numOfBytes) throws IOException { byte[] b = new byte[numOfBytes]; socket.getInputStream().read(b); return b; } public void sendMessage(byte[] msg) throws IOException { System.out.println("Sending to client"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream()); baos.write(SINGLE_FRAME_UNMASKED); baos.write(msg.length); baos.write(msg); baos.flush(); baos.close(); convertAndPrint(baos.toByteArray()); os.write(baos.toByteArray(), 0, baos.size()); os.flush(); } public void listenerThread() { Thread t = new Thread(new Runnable() { @Override public void run() { try { while (true) { System.out.println("Recieved from client: " + reiceveMessage()); System.out.println("Enter data to send"); } } catch (IOException ex) { ex.printStackTrace(); } } }); t.start(); } public String reiceveMessage() throws IOException { String EasyBytes = null; byte[] buf = readBytes(2); // our initial header convertAndPrint(buf); //System.exit(0); EasyBytes = (String.format("%02X ", buf[1])); int payloadadder = 0; if (EasyBytes.contains("FE")){ // Indicates extended message byte[] buf2 = readBytes(1); int a = (buf2[0] & 0xff) + 1; // if byte is zero there is one extra fragment so add 1! System.out.println("Number of extra bytes" + a); payloadadder = 2; // account for original header size byte[] adder = null; //String MagnificentString = ""; for (int x = 0; x < a; x++){ if(x==0){ adder = readBytes(1); //MagnificentString += String.format("%02X ", adder[0]); payloadadder += ((adder[0] & 0xFF) - 0x80);} if(x==1){ payloadadder = (buf[1] & 0xFF) + (adder[0] & 0xFF); } if(x>1){ payloadadder = (Integer.parseInt((String.format("%02X", buf2[0]) + String.format("%02X", adder[0])), 16)); //System.out.println(String.format("%02X", buf2[0]) + String.format("%02X", adder[0])); } } System.out.println("Overflow in byte/s " + payloadadder); //System.out.println("Our Hex String " + MagnificentString); //System.exit(0); } //convertAndPrint(buf); //dont use this byte[] buf2 = readBytes(4); System.out.println("Headers:"); //convertAndPrint(buf2);// Check out the byte sizes int opcode = buf[0] & 0x0F; if (opcode == 8) { //Client want to close connection! System.out.println("Client closed!"); socket.close(); System.exit(0); return null; } else { int payloadSize = 0; if (payloadadder <= 0){ payloadSize = getSizeOfPayload(buf[1]);} else { payloadSize = getSizeOfPayload(buf[1]) + payloadadder; } // if (extendedsize>=126){ //payloadSize = extendedsize;} System.out.println("Payloadsize: " + payloadSize); buf = readBytes(MASK_SIZE + payloadSize); System.out.println("Payload:"); convertAndPrint(buf); buf = unMask(Arrays.copyOfRange(buf, 0, 4), Arrays.copyOfRange(buf, 4, buf.length)); String message = new String(buf); return message; } } private int getSizeOfPayload(byte b) { //Must subtract 0x80 from masked frames int a = b & 0xff; //System.out.println("PAYLOAD SIZE INT" + a); return ((b & 0xFF) - 0x80); } private byte[] unMask(byte[] mask, byte[] data) { for (int i = 0; i < data.length; i++) { data[i] = (byte) (data[i] ^ mask[i % mask.length]); } return data; } private boolean convertAndPrintHeader(byte[] bytes) { StringBuilder sb = new StringBuilder(); String CaryOverDetection = new String(); // We must test byte 2 specifically for this. In the next step we add length bytes perhaps? //for(int i = 0; i < bytes.length; i++) { //} for (byte b : bytes) { CaryOverDetection = (String.format("%02X ", b)); if (CaryOverDetection.contains("FE")){ return false; } sb.append(String.format("%02X ", b)); } System.out.println(sb.toString()); return true; } private void convertAndPrint(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); } System.out.println(sb.toString()); } public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException { JfragWS j = new JfragWS(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { System.out.println("Write something to the client!"); j.sendMessage(br.readLine().getBytes()); } } } 
0
source share

All Articles