The ServerSocket constructor accepts a single parameter port of type int.
When you instantiate the ServerSocket class, it is bound to the port number you specified by the port argument.
Here's an implementation split into parts:
java
importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.net.ServerSocket;importjava.net.Socket;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.Base64;importjava.util.Scanner;importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassWebSocket{publicstaticvoidmain(String[] args)throwsIOException,NoSuchAlgorithmException{ServerSocket server =newServerSocket(80);try{System.out.println("Server has started on 127.0.0.1:80.\r\nWaiting for a connection…");Socket client = server.accept();System.out.println("A client connected.");
Writes len bytes from the specified byte array starting at offset off to this output stream.
InputStream Methods
java
read(byte[] b,int off,int len)
Reads up to len bytes of data from the input stream into an array of bytes.
Let us extend our example.
java
InputStream in = client.getInputStream();OutputStream out = client.getOutputStream();Scanner s =newScanner(in,"UTF-8");
Handshaking
When a client connects to a server, it sends a GET request to upgrade the connection to a WebSocket from a simple HTTP request. This is known as handshaking.
java
try{String data = s.useDelimiter("\\r\\n\\r\\n").next();Matcher get =Pattern.compile("^GET").matcher(data);
Creating the response is easier than understanding why you must do it in this way.
You must,
Obtain the value of Sec-WebSocket-Key request header without any leading and trailing whitespace
Link it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
Compute SHA-1 and Base64 code of it
Write it back as value of Sec-WebSocket-Accept response header as part of an HTTP response.
After a successful handshake, client can send messages to the server, but now these are encoded.
If we send "abcdef", we get these bytes:
129 134 167 225 225 210 198 131 130 182 194 135
129:
FIN (Is this the whole message?)
RSV1
RSV2
RSV3
Opcode
1
0
0
0
0x1=0001
FIN: You can send your message in frames, but now keep things simple. Opcode 0x1 means this is a text. Full list of Opcodes
134: If the second byte minus 128 is between 0 and 125, this is the length of the message. If it is 126, the following 2 bytes (16-bit unsigned integer), if 127, the following 8 bytes (64-bit unsigned integer, the most significant bit MUST be 0) are the length.
Note: It can take 128 because the first bit is always 1.
167, 225, 225 and 210 are the bytes of the key to decode. It changes every time.
The remaining encoded bytes are the message.
Decoding algorithm
decoded byte = encoded byte XOR (position of encoded byte BITWISE AND 0x3)th byte of key
Example in Java:
java
byte[] decoded =newbyte[6];byte[] encoded =newbyte[]{(byte)198,(byte)131,(byte)130,(byte)182,(byte)194,(byte)135};byte[] key =newbyte[]{(byte)167,(byte)225,(byte)225,(byte)210};for(int i =0; i < encoded.length; i++){
decoded[i]=(byte)(encoded[i]^ key[i &0x3]);}}}finally{
s.close();}}finally{
server.close();}}}