I'm writing a Client/Server application where the client sends a server a username and the server responds with a challenge however I'm having issues with the client receiving the challenge. It seems as though the challenge is just getting dropped or replaced with another array of bytes (which happens to be exactly the same each time). Any suggestions for this would be much appreciated.
Client Code:
public class ClientOrig {
public static void main( String[] args ) {
// Complain if we don't get the right number of arguments.
if ( args.length != 1 ) {
System.out.println( "Usage: Client <host>" );
System.exit( -1 );
}
try {
// Try to create a socket connection to the server.
Socket sock = new Socket( args[ 0 ], ServerOriginal.PORT_NUMBER );
// Get formatted input/output streams for talking with the server.
DataInputStream input = new DataInputStream( sock.getInputStream() );
DataOutputStream output = new DataOutputStream( sock.getOutputStream() );
// Get a username from the user and send it to the server.
Scanner scanner = new Scanner( System.in );
System.out.print( "Username: " );
String name = scanner.nextLine();
output.writeUTF( name );
output.flush();
byte[] challenge = ServerOriginal.getMessage( input );
System.out.println(challenge);
String request = "";
System.out.print( "cmd> " );
// We are done communicating with the server.
sock.close();
} catch( IOException e ){
System.err.println( "IO Error: " + e );
}
}
}
Server Code:
public static byte[] getMessage( DataInputStream input ) throws IOException {
int len = input.readInt();
byte[] msg = new byte [ len ];
input.readFully( msg );
System.out.println("Read: " + msg + " which is " + msg.length);
System.out.println("Byte to string: " + new String(msg));
return msg;
}
/** Function analogous to the previous one, for sending messages. */
public static void putMessage( DataOutputStream output, byte[] msg ) throws IOException {
output.writeInt(msg.length);
output.write( msg, 0, msg.length );
System.out.println("Writing: "+ msg + " which is " + msg.length);
output.flush();
}
/** Function to handle interaction with a client. Really, this should
be run in a thread. */
public void handleClient( Socket sock ) {
try {
// Get formatted input/output streams for this thread. These can read and write
// strings, arrays of bytes, ints, lots of things.
DataOutputStream output = new DataOutputStream( sock.getOutputStream() );
DataInputStream input = new DataInputStream( sock.getInputStream() );
// Get the username.
String username = input.readUTF();
System.out.println(username);
// Make a random sequence of bytes to use as a challenge string.
Random rand = new Random();
byte[] challenge = new byte [ 16 ];
System.out.println(challenge);
rand.nextBytes( challenge );
System.out.println(challenge);
putMessage(output, challenge);
// Send the client the challenge.
putMessage( output, challenge );
getMessage(input);
} catch ( IOException e ) {
System.out.println( "IO Error: " + e );
} finally {
try {
// Close the socket on the way out.
sock.close();
} catch ( Exception e ) {
}
}
}
Related
There are two files (client file, server file) in this program that are supposed to be able to send and receive messages (utf-8 strings) to each other. Each file has a thread (one thread for client, one thread for server)
The client and the server connect on localhost with a port number (it should be the same port number when typing on the command prompt / mac terminal window)
However, the server is supposed to only send messages to all the other clients after receiving a message from a client. In other words, if a client sends a message to the server, the server cannot send that message back to the same client--it can only send messages to the different clients.
Another way to say it: Once a client is connected, it can send messages to the server. It will also receive from the server all messages sent from the other connected clients (not the messages sent from itself).
At runtime, there is supposed to be only one server (mac terminal / command prompt windows) but there can be multiple/infinite number of clients (mac terminal / command prompt windows)
Screenshot of error (server side):
Screenshot of error (client side):
Code of ChatServer.java:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.nio.charset.StandardCharsets.*;
public class ChatServer
{
private static Socket socket;
public static void main(String args[])
{
Thread ChatServer1 = new Thread ()
{
public void run ()
{
System.out.println("Server thread is now running");
try
{
int port_number1 = 0;
int numberOfClients = 0;
boolean KeepRunning = true;
if(args.length>0)
{
port_number1 = Integer.valueOf(args[0]);
}
System.out.println("Waiting for connections on port " + port_number1);
try
{
ServerSocket serverSocket = new ServerSocket(port_number1);
}
catch (IOException e)
{
e.printStackTrace();
}
System.out.println( "Listening for connections on port: " + ( port_number1 ) );
while(KeepRunning)
{
ServerSocket serverSocket = new ServerSocket(port_number1);
//create a list of clients
ArrayList<String> ListOfClients = new ArrayList<String>();
//connect to client
socket = serverSocket.accept();
//add new client to the list, is this the right way to add a new client? or should it be in a for loop or something?
ListOfClients.add("new client");
numberOfClients += 1;
System.out.println("A client has connected. Waiting for message...");
ListOfClients.add("new client" + numberOfClients);
//reading encoded utf-8 message from client, decoding from utf-8 format
String MessageFromClientEncodedUTF8 = "";
BufferedReader BufReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String MessageFromClientDecodedFromUTF8 = BufReader1.readLine();
byte[] bytes = MessageFromClientEncodedUTF8.getBytes("UTF-8");
String MessageFromClientDecodedUTF8 = new String(bytes, "UTF-8");
//relaying message to every other client besides the one it was from
for (int i = 0; i < ListOfClients.size(); i++)
{
if(ListOfClients.get(i)!="new client")
{
String newmessage = null;
String returnMessage = newmessage;
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage + "\n");
System.out.println("Message sent to client: "+returnMessage);
bw.flush();
}
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (socket != null)
{
socket.close ();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
};
ChatServer1.start();
}
}
Code of ChatClient.java:
import java.io.*;
import java.net.*;
import java.util.*;
import static java.nio.charset.StandardCharsets.*;
public class ChatClient
{
private static Socket Socket;
static int numberOfClients = 0;
public static void main(String args[])
{
//If I wanted to create multiple clients, would this code go here? OR should the new thread creation be outside the while(true) loop?
while (true)
{
String host = "localhost";
int numberOfClients = 0;
Thread ChatClient1 = new Thread ()
{
public void run()
{
try
{
//Client begins, gets port number, listens, connects, prints out messages from other clients
int port = 0;
int port_1number1 = 0;
int numberofmessages = 0;
String[] messagessentbyotherclients = null;
System.out.println("Try block begins..");
System.out.println("Chat client is running");
String port_number1= args[0];
System.out.println("Port number is: " + port_number1);
if(args.length>0)
{
port = Integer.valueOf(port_number1);
}
System.out.println("Listening for connections..");
System.out.println( "Listening on port: " + port_number1 );
Socket.connect(null);
System.out.println("Client has connected to the server");
for(int i = 0; i < numberOfClients; i++)
{
System.out.println(messagessentbyotherclients);
}
//client creates new message from standard input
OutputStream os = Socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//creating message to send from standard input
String newmessage = "";
try
{
// input the message from standard input encoded in UTF-8 string format
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String line = "";
System.out.println( "Standard input (press enter then control D when finished): " );
while( (line= input.readLine()) != null )
{
newmessage += line + " ";
input=null;
}
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
}
//Sending the message to server
String sendMessage = newmessage;
bw.write(sendMessage + "\n");
bw.flush();
System.out.println("Message sent to server: "+sendMessage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
ChatClient1.start();
}
}
}
These two errors have been covered many times and I've heard that the answer is to put the socket in a loop, which it already is in (while loop).
My question is: Is there a way to locate the errors before running it? Whenever I compile the program I don't get any errors in eclipse, but when I run it in the command prompt window / mac terminal, it does tell me that something is wrong. Or perhaps there's a line of code that I'm overlooking?
ServerSocket serverSocket = new ServerSocket(port_number1);
Place it once, before the while loop.
I need a bufferread to work with a client which closes when the word "CLOSE". THE client closes, I just can't get the sever to close once messages have been sent through it.
Heres what code I have:
`
import java.io.*;
import java.net.*;
class TCPClient2 {
public static void main(String argv[]) throws Exception {
String sentence;
String modifiedSentence;
BufferedReader inFromUser
= new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("143.53.30.136", 49250);//port number and ip address of client
DataOutputStream outToServer
= new DataOutputStream(clientSocket.getOutputStream());
InputStream sin = clientSocket.getInputStream();
// Just converting them to different streams, so that string handling becomes easier.
DataInputStream inFromServer = new DataInputStream(sin);
try {
do {
System.out.print("Enter message : ");
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
//Question B4
//if statement for closing the socket connection
if (sentence.equals("CLOSE")) {
clientSocket.close();
//closes client socket
System.out.println("Socket Closed");
//prints socket closed to tell user socket has closed
System.exit(0);
}
outToServer.writeBytes(sentence + '\n');
System.out.print("Message sent! please wait for server message: ");
modifiedSentence = inFromServer.readUTF();
System.out.println("FROM SERVER: " + modifiedSentence);
} while (!sentence.equals("CLOSE"));
} catch (IOException e) {
}
clientSocket.close();
}
}`
AND the server:
`
/*
chris and paul
*/
import java.io.*;
import java.net.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TCPMultiThreadServer {
private static ServerSocket welcomeSocket;
//port number the server is using
private static final int PORT = 49250;
private static int clientNo =1;
public static void main(String argv[]) throws Exception
{
System.out.println("Opening port...\n");
try
{
// ServerSocket listens for new connections on specified port
welcomeSocket = new ServerSocket(PORT);
do
{
Socket client = welcomeSocket.accept();
System.out.println("\nNew client accepted.\n");
//Create a thread to handle communication with
//this client and pass the constructor for this
//thread a reference to the relevant socket...
TCPMultiThreadServer.ClientHandler handler =
new TCPMultiThreadServer().new ClientHandler(client,clientNo);
handler.start(); // Calls run() method in ClientHandler
clientNo++;
} while (true);
} catch (IOException e) {}
}
// Original work not credited
class ClientHandler extends Thread
{
private Socket client;
private BufferedReader inFromClient;
private BufferedReader text_to_Client;
private DataOutputStream outToClient;
private FileWriter Filestream;
private BufferedWriter out;
public int clientNo;
public boolean stopping;
//part A question 4, adding buffer string array to the program
private String[] buffer; //creation of buffer string array.
private int bufferI; // Index of the last thing inserted into the array
public ClientHandler(Socket socket, int clientNos)
{
//Set up reference to associated socket
client = socket;
clientNo= clientNos;
try
{
// Gets access to input/output stream of socket
inFromClient =
new BufferedReader(new InputStreamReader
(client.getInputStream()));
text_to_Client =
new BufferedReader(new InputStreamReader(System.in));
outToClient =
new DataOutputStream(client.getOutputStream());
} catch(IOException e) {}
}
public void run()
{
try
{
stopping = false;
//Question A4 buffer continued
buffer = new String[4];
//generates buffer string array containing 4 strings
bufferI = 0;
// make sure bufferIndex = 0
String clientSentence;
Thread mythread = Thread.currentThread();
do
{
//Accept message from client on socket's input stream
OutputStream sout = client.getOutputStream();
// Just converting them to different streams, so that string
// handling becomes easier.
DataOutputStream text_to_send = new DataOutputStream(sout);
clientSentence = inFromClient.readLine();
System.out.println("Message received from client number " +
clientNo + ": "+ clientSentence);
// String to be scanned to find the pattern.
String line = clientSentence;
String pattern = "[C][L][O][S][E]";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
//if (m.find( )) {
// System.out.println("Found value: " + m.find() );
// System.out.println("Found value: " + m.group(1) );
//System.out.println("Found value: " + m.group(2) );
//} else {
// System.out.println("NO MATCH");
//}
//part B question 4 close command
//if statement for closing the socket connection if it is equal to close
if(m.matches())
{ //prints socket closed to tell user socket has closed
System.out.println("Socket connection to client number "
+ clientNo + " closed");
try
{
} catch(Exception e) {}
out.flush();
out.close(); // Close the file handler
client.close(); // Close the connection with the client,
clientNo--; // Decrement the number of clients
}
else
{
//part A question 4, adding buffer string array to the program
// looks to see if the buffer string array is full
//and also looks to see if bufferIndex is in range
if (bufferI > buffer.length-1)
{
// Print BUFFER FULL
System.out.println("BUFFER FULL");
// Clear clientSentence string
clientSentence = " ";
// For loop which travels through the buffer array of string
for (int i=0; i<buffer.length; i++)
{
// Append buffer element to clientSentence string
clientSentence += buffer[i] + " , ";
buffer[i] = null; // makes the buffer null
}
bufferI = 0; // Reset bufferI back to 0 so writing to the buffer can restarted
// prints buffer cleared back to the clients
text_to_send.writeUTF("BUFFER CLEARED :" +
clientSentence);
}
else
{
buffer[bufferI] = clientSentence;
System.out.println("Buffer " + bufferI+ ": " +
buffer[bufferI]);
bufferI++;
System.out.println("Enter Message: ");
// Reads message from server interface
// and sends it to the client
clientSentence = text_to_Client.readLine();
text_to_send.writeUTF(clientSentence);
System.out.println("Your message: " +
clientSentence);
}
}
if (mythread.activeCount() == 2 &&
(clientNo ==0 || clientNo >0) &&
clientSentence.equals("CLOSE"))
{
System.exit(0);
}
} while(!clientSentence.equals("CLOSE"));
client.close();
} catch(IOException e) {}
}
}
}
`
I have a task to do this.
Create a client and server socket interaction which accepts byte data and converts the byte data data received at server in the String and send back the response with the confirmation of the data conversation with success/unsuccess as the data passed will be with fix data length format so the validation should be done at server end.
As for e.g.
there are fields which ur sending to server like,
field 1 - number
field 2 - String
field 3 as Floating number i.e. 108.50
After conversion from byte to String :
152|any msg|108.50
In Byte it will be something like this,
10101|1001010010000000011000000000|1110111011
I have tried the following programs to do this
Server.java
public class Server extends Thread
{
private ServerSocket serverSocket;
public Server(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(100000);
}
public void run()
{
while(true)
{
try
{
Socket server = serverSocket.accept();
byte Message[]=null;
DataInputStream in =
new DataInputStream(server.getInputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
System.out.println("On this line"); //This doesnt get printed
buffer.flush();
data= buffer.toByteArray();
System.out.println(data);
String convertmsg = new String(data);
System.out.println("Msg converted "+convertmsg);
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
System.out.println("below dataoutputstream");
out.write("Success".getBytes());
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 4003;
try
{
Thread t = new Server(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
client
public class Client {
public static void main(String args[]) throws IOException
{
int userinput =1;
while(userinput==1)
{
String serverName = "192.168.0.8";
int port = 4003;
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
System.out.println("above out.wirte()");
out.write("any msg".getBytes());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
System.out.println("converting array "+in);
byte[] data = IOUtils.toByteArray(in);
System.out.println(data);//This line doesnt get printed
//System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
System.out.println("Enter userinput ");
DataInputStream dis = new DataInputStream(System.in);
String s = dis.readLine();
userinput = Integer.parseInt(s);
}
}
}
If i send data from client to server in bytes,it reads it and prints it.Also then the line "Enter userinput " gets printed and if the user enters '1' the program continues.
But the problem is this program given above. If i try to send data from server stating "success"(meaning the data has been converted from bytes to String successfully) then the program stucks and the cursor doesnt go below the line which are in comments "This line doesnt get printed".There is no error printed and none of the program terminates.I am new to socket programming and dont understand much about networking.
Any help will be truly appreciated.
You're reading the input until end of stream, but the peer isn't closing the connection, so end of stream never arrives.
I suggest you read and write lines, or use writeUTF() and readUTF().
I'm implementing a WebSocket server (for learning purposes) and I have it correctly handling the handshake (websocket.onopen is called so I assume this means handshake was successful), however, when the client (browser) sends a message after the handshake, the server never receives it.
Using Chrome's developer tools, I'm able to see that all the headers were correctly received and no errors are thrown. It also says that it sent the "hello" despite the readLine() never firing in Java.
What's wrong in my code?
EDIT 1: I discovered that if I refresh the web page, then (and only then) the ServerSocket receives the data from the last connection (that the refresh just killed)! Why is this the only way it receives it?
EDIT 2: I also found that I can send a message to the client after the handshake and the client receieves it but STILL the server never receives the client's message! I sent the message to the client like this:
byte[] message = new byte[ 7 ];
message[ 0 ] = new Integer(129).byteValue();
message[ 1 ] = new Integer(5).byteValue();
byte[] raw = "hello".getBytes();
message[ 2 ] = raw[ 0 ];
message[ 3 ] = raw[ 1 ];
message[ 4 ] = raw[ 2 ];
message[ 5 ] = raw[ 3 ];
message[ 6 ] = raw[ 4 ];
outStream.write( message);
out.println();
HTML PAGE
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebSocket Test</title></head>
<body>
<script>
try
{
function writeToScreen(message)
{
var p = document.createElement( "p" );
p.innerHTML = message;
document.getElementsByTagName( "body" )[ 0 ].appendChild( p );
}
function onOpen(evt)
{
writeToScreen( "opened" );
doSend( "hello" );
//We reach here but the server never recieves the message! (and bufferedAmount == 0)
writeToScreen( "sent: " + websocket.bufferedAmount );
}
function onClose(evt)
{
alert( "closed" );
websocket.close();
}
function onMessage(evt)
{
alert( "Message: " + evt.data );
}
function onError(evt)
{
alert( "Error: " + evt );
}
function doSend (message)
{
websocket.send( message );
}
//PUT IN YOUR OWN LOCAL IP ADDRESS HERE TO GET IT TO WORK
var websocket = new WebSocket( "ws://192.168.1.19:4444/" );
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;
}
catch(e)
{
}
</script>
</body>
</html>
JAVA CODE
import java.net.*;
import java.io.*;
import java.security.*;
public class WebListener
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening) new ServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
class ServerThread extends Thread {
private Socket socket = null;
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run() {
try {
OutputStream outStream = null;
PrintWriter out = new PrintWriter( outStream = socket.getOutputStream(), true);
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
String inputLine, outputLine;
//Handle the headers first
doHeaders( out, in );
//Now read anything they have to send
while ( ( inputLine = in.readLine() ) != null )
{
//WE NEVER REACH HERE!
System.out.println( inputLine );
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void doHeaders(PrintWriter out, BufferedReader in) throws Exception
{
String inputLine = null;
String key = null;
//Read the headers
while ( ( inputLine = in.readLine() ) != null )
{
//Get the key
if ( inputLine.startsWith( "Sec-WebSocket-Key" ) ) key = inputLine.substring( "Sec-WebSocket-Key: ".length() );
//They're done
if ( inputLine.equals( "" ) ) break;
}
//We need a key to continue
if ( key == null ) throw new Exception( "No Sec-WebSocket-Key was passed!" );
//Send our headers
out.println( "HTTP/1.1 101 Web Socket Protocol Handshake\r" );
out.println( "Upgrade: websocket\r" );
out.println( "Connection: Upgrade\r" );
out.println( "Sec-WebSocket-Accept: " + createOK( key ) + "\r" );
out.println( "\r" );
}
public String createOK(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException, Exception
{
String uid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String text = key + uid;
MessageDigest md = MessageDigest.getInstance( "SHA-1" );
byte[] sha1hash = new byte[40];
md.update( text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
return new String( base64( sha1hash ) );
}
public byte[] base64(byte[] bytes) throws Exception
{
ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
OutputStream out = new Base64.OutputStream(out_bytes); //Using http://iharder.net/base64
out.write(bytes);
out.close();
return out_bytes.toByteArray();
}
private String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
}
WebSocket messages are not terminated by \r\n so you can't use in.readline() to read them. See the data framing section of the spec for how to messages are constructed.
For text messages from client (browser) to server, messages will have the form:
(byte)0x81
1, 3 or 9 byte structure indicating message length and whether the message body is masked. (Messages from a browser should always be masked.)
4 byte mask
Message (utf-8 encoded)
There is no end-of-message marker you can search for. You just need to read the first few bytes of a client request to figure out the length of its payload.
your code WebListener must running on windows, and you will find out line.separator is CRLF
byte[] lineSeperator=System.getProperty("line.separator").getBytes();
System.out.println("line seperator: "+Arrays.toString(lineSeperator));
In your response header
out.println( "Header xxxx"+ "\r" );
so header is ended with \r\r\n
Per HTTP rfc2616
Response = Status-Line ; Section 6.1
*(( general-header ; Section 4.5
| response-header ; Section 6.2
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 7.2
Client don't can not decode your header with \r\r\n.
When I open a websocket connection to my websocket server application from Java, the server sees two connections. The first one never sends any data and the second one sends all the proper headers, etc. Anyone know what the reason for this is?
Client side connection is:
var websocket = new WebSocket( "ws://192.168.1.19:3333/websession" );
On the server side, in a while loop I call "serverSocket.accept()" and this gets called twice. But one of them never sends any data (the in.read() simply times out eventually without returning anything).
JAVA SERVER CODE
import java.net.*;
import java.io.*;
import java.security.*;
public class WebListener {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening) new ServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
class ServerThread extends Thread {
private Socket socket = null;
public ServerThread(Socket socket) {
super("ServerThread");
this.socket = socket;
}
public void run() {
try {
OutputStream outStream = null;
PrintWriter out = new PrintWriter( outStream = socket.getOutputStream(), true);
BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream()));
String inputLine, outputLine;
//Handle the headers first
doHeaders( out, in );
// ..elided..
out.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void doHeaders(PrintWriter out, BufferedReader in) throws Exception {
String inputLine = null;
String key = null;
//Read the headers
while ( ( inputLine = in.readLine() ) != null ) {
//Get the key
if ( inputLine.startsWith( "Sec-WebSocket-Key" ) )
key = inputLine.substring( "Sec-WebSocket-Key: ".length() );
//They're done
if ( inputLine.equals( "" ) ) break;
}
//We need a key to continue
if ( key == null ) throw new Exception( "No Sec-WebSocket-Key was passed!" );
//Send our headers
out.println( "HTTP/1.1 101 Web Socket Protocol Handshake\r" );
out.println( "Upgrade: websocket\r" );
out.println( "Connection: Upgrade\r" );
out.println( "Sec-WebSocket-Accept: " + createOK( key ) + "\r" );
out.println( "\r" );
}
public String createOK(String key) throws NoSuchAlgorithmException, UnsupportedEncodingException, Exception {
String uid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String text = key + uid;
MessageDigest md = MessageDigest.getInstance( "SHA-1" );
byte[] sha1hash = new byte[40];
md.update( text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
return new String( base64( sha1hash ) );
}
public byte[] base64(byte[] bytes) throws Exception {
ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
OutputStream out = new Base64.OutputStream(out_bytes); //Using http://iharder.net/base64
out.write(bytes);
out.close();
return out_bytes.toByteArray();
}
private String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
}
This looks to be a bug with Firefox. In Chrome it only opens one connection, while the same page in Firefox 15 opens two connections.