aquaballoon

Java socket + HTML5 websocket

Jun 12th, 2014
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.30 KB | None | 0 0
  1. // Server.java <=== Server
  2. package webSocket;
  3.  
  4. import java.io.IOException;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. import java.security.NoSuchAlgorithmException;
  8. import java.util.ArrayList;
  9. import java.util.StringTokenizer;
  10.  
  11. public class Server {
  12.  
  13.     ArrayList<NewClient> clientArray = new ArrayList<NewClient>();
  14.  
  15.     int PORT = 4447;
  16.  
  17.     private ServerSocket serverSocket;
  18.     private Socket clientSocket;
  19.  
  20.     public Server() throws IOException, Exception {
  21.         serverSocket = new ServerSocket(PORT);
  22.         System.out.println("Server Connected...");
  23.        
  24.         while (true) {
  25.             clientSocket = serverSocket.accept(); //accept new client
  26.             NewClient newClient = new NewClient(this, clientSocket);
  27.             newClient.start();
  28.            
  29.             // clientArray will be added after receiving message from client
  30.             clientArray.add(newClient);
  31.         }
  32.     }
  33.  
  34. //    public void broadcast(String msgFromClient) throws IOException {
  35. //        // send message to all connected usersArray
  36. //        synchronized (clientArray) {
  37. //            for (NewClient newClient : clientArray) {
  38. //                newClient.sendToMe(msgFromClient.getBytes());
  39. //            }
  40. //        }
  41. //    }
  42.  
  43.     public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException, Exception {
  44.         new Server();
  45.     }
  46. }
  47.  
  48.  
  49. //NewClient.java  <=== Server
  50. package webSocket;
  51.  
  52. import java.io.*;
  53. import java.net.*;
  54. import java.security.MessageDigest;
  55. import java.security.NoSuchAlgorithmException;
  56. import java.util.Arrays;
  57. import java.util.HashMap;
  58. import java.util.StringTokenizer;
  59. import sun.misc.BASE64Encoder;
  60.  
  61. public class NewClient extends Thread {
  62.  
  63.     Socket clientSocket;
  64.     Server server;
  65.  
  66.     String loginName = "";
  67.     String loginIP = "";
  68.  
  69.     BufferedReader in;
  70.     PrintWriter out;
  71.  
  72.     public static final int MASK_SIZE = 4;
  73.     public static final int SINGLE_FRAME_UNMASKED = 0x81;
  74.  
  75.     public NewClient(Server server, Socket client) throws IOException {
  76.  
  77.         this.clientSocket = client;
  78.         this.server = server;
  79.  
  80.         in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  81.         out = new PrintWriter(clientSocket.getOutputStream());
  82.  
  83.         if (handshake()) {
  84.  
  85.             try {
  86.                 // LOGIN
  87.                 String loginInfo = receiveMessage();  //first data from client
  88.                 // userName@/127.0.0.1 => (userName, userIP)
  89.                 StringTokenizer tok = new StringTokenizer(loginInfo, "@");
  90.  
  91.                 loginName = tok.nextToken();
  92.  
  93.                 String tempLogin = "Welcome " + loginName;
  94.                 sendToMe(tempLogin.getBytes());
  95.  
  96.                 // new user
  97.                 if (server.clientArray.size() > 0) {
  98.                     String temp = "";
  99.                     for (NewClient newClient : server.clientArray) {
  100.                         temp += (newClient.loginName) + "@";
  101.                     }
  102.                     // send other's login info to me
  103.                     String tempUserlist = "USERLIST@" + server.clientArray.size() + "@" + temp;
  104.                     sendToMe(tempUserlist.getBytes());
  105.                 }
  106.  
  107.                 // old user
  108.                 for (NewClient newClient : server.clientArray) {
  109.                     // send my login info to other
  110.                     String tempAdd = "ADD@" + loginName;
  111.                     newClient.sendToMe(tempAdd.getBytes());
  112.                 }
  113.             } // try
  114.             catch (Exception e) {
  115.                 System.out.println(e.getMessage());
  116.             }
  117.         }
  118.     }
  119.  
  120.     public void run() {
  121.         String msgFromClient = null;
  122.         // msgFromClient = username@ALL@hello world
  123.         while (true) {
  124.             try {
  125.                 msgFromClient = receiveMessage();
  126.  
  127.                 if (msgFromClient.equals("CLOSE")) {
  128.  
  129.                     for (NewClient newClient : server.clientArray) {
  130.                         String tempDelete = "DELETE@" + loginName;
  131.                         newClient.sendToMe(tempDelete.getBytes());
  132.                     }
  133.  
  134.                     server.clientArray.remove(this);
  135.  
  136.                     in.close();
  137.                     out.close();
  138.                     clientSocket.close();
  139.                     return;  // or break;
  140.  
  141.                     //break;
  142.                 } else {
  143.  
  144.                     // msgFromClient = username@ALL@hello world
  145.                     StringTokenizer token = new StringTokenizer(msgFromClient, "@");
  146.  
  147.                     String sender = token.nextToken();
  148.                     String receiver = token.nextToken();
  149.                     String content = token.nextToken();
  150.  
  151.                     for (NewClient newClient : server.clientArray) {
  152.                         if (receiver.equals("ALL")) {
  153.                             if (!sender.equals(newClient.getUserName())) {
  154.                                 msgFromClient = sender + ": " + content;
  155.                                 newClient.sendToMe(msgFromClient.getBytes());
  156.                             } else {
  157.                                 msgFromClient = "Me" + ": " + content;
  158.                                 sendToMe(msgFromClient.getBytes());
  159.                             }
  160.                         } else if (!receiver.equals("ALL")) {
  161.                             if (newClient.getUserName().equals(receiver)) {
  162.                                 msgFromClient = sender + ": " + content;
  163.                                 newClient.sendToMe(msgFromClient.getBytes());
  164.                             }
  165.                         }
  166.                     }
  167.                 }
  168.             } catch (IOException e) {
  169.                 e.printStackTrace();
  170.             }
  171.         }// end of while
  172.     }
  173.  
  174.     private boolean handshake() throws IOException {
  175.         //PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
  176.         //BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  177.  
  178.         HashMap<String, String> keys = new HashMap<>();
  179.         String str;
  180.  
  181.         //Reading clientSocket handshake / request from clientSocket
  182.         while (!(str = in.readLine()).equals("")) {
  183.             String[] s = str.split(": ");
  184.             if (s.length == 2) {
  185.                 keys.put(s[0], s[1]);
  186.             }
  187.         }
  188.  
  189.         String respondingHash;
  190.         try {
  191.             respondingHash = new BASE64Encoder().encode(MessageDigest.getInstance("SHA-1")
  192.                     .digest((keys.get("Sec-WebSocket-Key")
  193.                             + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes()));
  194.  
  195.         } catch (NoSuchAlgorithmException ex) {
  196.             ex.printStackTrace();
  197.             return false;
  198.         }
  199.  
  200.         //Write handshake / response to clientSocket
  201.         out.write("HTTP/1.1 101 Switching Protocols\r\n"
  202.                 + "Upgrade: websocket\r\n"
  203.                 + "Connection: Upgrade\r\n"
  204.                 + "Sec-WebSocket-Accept: " + respondingHash + "\r\n"
  205.                 + "\r\n");
  206.         out.flush();
  207.  
  208.         return true;
  209.     }
  210.  
  211.     public void sendToMe(byte[] msg) throws IOException {
  212.         //System.out.println("Sending to clientSocket");
  213.  
  214.         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  215.         BufferedOutputStream os = new BufferedOutputStream(clientSocket.getOutputStream());
  216.  
  217.         baos.write(SINGLE_FRAME_UNMASKED);  //fisrt byte(0x81): text type
  218.         baos.write(msg.length); //frame in second byte: text length
  219.         baos.write(msg);  //0x81 + msg length + msg
  220.         baos.flush();
  221.         baos.close();
  222.  
  223.         os.write(baos.toByteArray(), 0, baos.size());  //send message in bytes
  224.         os.flush();
  225.     }
  226.  
  227.     public String receiveMessage() throws IOException {
  228.  
  229.         byte[] buf = readBytes(2); //reading two bytes from clientSocket
  230.  
  231.         int opcode = buf[0] & 0x0F;  //first byte(0x81) & 0x0F(00001111)
  232.  
  233.         if (opcode == 8) { //opcode 8 is close connection
  234.             System.out.println("Client left!");
  235.  
  236.             for (NewClient newClient : server.clientArray) {
  237.                 String tempDelete = "DELETE@" + loginName;
  238.                 newClient.sendToMe(tempDelete.getBytes());
  239.             }
  240.  
  241.             server.clientArray.remove(this);
  242.  
  243. //            in.close();
  244. //            out.close();
  245. //            clientSocket.close();
  246.             closeCon();
  247.  
  248.             return null;  // error without "return"
  249.  
  250.         } else {  // opcode == 1 / first byte => text type
  251.  
  252.             //length of message text
  253.             final int msgLength = getSizeOfMessage(buf[1]);
  254.  
  255.             buf = readBytes(MASK_SIZE + msgLength); //MASK_SIZE = 4 bytes
  256.  
  257.             // convert message(byte) to string  // 4 ==> mask size 4 bytes
  258.             buf = unMask(Arrays.copyOfRange(buf, 0, 4), Arrays.copyOfRange(buf, 4, buf.length));
  259.             String message = new String(buf); // message in byte to String
  260.             return message;
  261.         }
  262.     }
  263.  
  264.     private byte[] readBytes(int numOfBytes) throws IOException {
  265.         byte[] b = new byte[numOfBytes];
  266.         clientSocket.getInputStream().read(b);  //message from clientSocket
  267.         return b;
  268.     }
  269.  
  270.     // get the length of text message
  271.     private int getSizeOfMessage(byte b) {
  272.         //Must subtract 0x80 from masked frames
  273.         return ((b & 0xFF) - 0x80);
  274.     }
  275.  
  276.     // extract only text message removing mask 4 bytes
  277.     private byte[] unMask(byte[] mask, byte[] data) {  // mask = 4 bytes
  278.         for (int i = 0; i < data.length; i++) {
  279.             data[i] = (byte) (data[i] ^ mask[i % mask.length]);
  280.         }
  281.         return data;
  282.     }
  283.  
  284.     public String getUserName() {
  285.         return loginName;
  286.     }
  287.  
  288.     public void closeCon() throws IOException {
  289.         in.close();
  290.         out.close();
  291.         clientSocket.close();
  292.         return;  // or break;
  293.     }
  294. }
  295.  
  296. //websocket.html <=== Client
  297. <!DOCTYPE HTML>
  298. <html>
  299. <body>
  300.  
  301. Instruction;<br><br>
  302.  
  303. LOGIN: username@ <br>
  304. * from server: <br>
  305. * welcome username<br>
  306. * USERLISTf@numOfUser@user, or<br>
  307. * ADDf@user<br><br>
  308.  
  309. MESSAGE: username@ALL@hello wolrd <br>
  310. MESSAGE to receiver: username@receiver@hello receiver <br>
  311. * from server: <br>
  312. * username: hello world<br><br>
  313.  
  314. <button type="button" onclick="connect();">Connect</button>
  315. <button type="button" onclick="connection.close()">Close</button>
  316.  
  317. <form>
  318. <input type="text" id="msg" />
  319.  
  320. <button type="button" onclick="sendMsg();">Send message!</button>
  321.  
  322. <script>
  323. var connection;
  324.  
  325. function connect() {
  326.     console.log("connection");
  327.     connection = new WebSocket("ws://localhost:4447/");
  328.     // Log errors
  329. connection.onerror = function (error) {
  330.   console.log('WebSocket Error ');
  331.   console.log(error);
  332.  
  333. };
  334.  
  335. // Log messages from the server
  336. connection.onmessage = function (e) {
  337.   console.log('Server: ' + e.data);
  338.   alert(e.data);
  339. };
  340.  
  341. connection.onopen = function (e) {
  342. console.log("Connection open...");
  343. alert("Connection open...");
  344. }
  345.  
  346. connection.onclose = function (e) {
  347. console.log("Connection closed...");
  348. alert("Connection closed...");
  349. }
  350. }
  351. // end of Log messages from the server
  352.  
  353. function sendMsg() {
  354.     connection.send(document.getElementById("msg").value);
  355. }
  356.  
  357. function close() {
  358.     console.log("Closing...");
  359.     connection.close();
  360. }
  361. </script>
  362. </body>
  363.  
  364. </html>
Advertisement
Add Comment
Please, Sign In to add comment