ServerSocket doesn't work with try-with-resources? - java

So we're fooling around with ServerSockets in class, making a very simple HTTP server that takes a request, does nothing with it, and responds with a 200 OK followed by some HTML content.
I've been trying to figure out this problem for two days, and I haven't been able to get to grips with it, and neither has my teacher. I've come to think it is a problem with closing the server, for some odd reason. I've fixed the problem, but would just like to know why I happened in the first place.
Here are three snippets:
HttpServer.class:
package httpserver;
import java.io.Closeable;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class HttpServer implements Closeable {
public static final int PORT = 80;
public static final int BACKLOG = 1;
public static final String ROOT_CATALOG = "C:/HttpServer/";
private ServerSocket server;
private Socket client;
private Scanner in;
private PrintWriter out;
private String request;
public HttpServer() throws IOException {
server = new ServerSocket(PORT, BACKLOG);
}
public Socket accept() throws IOException {
client = server.accept();
in = new Scanner(client.getInputStream());
out = new PrintWriter(client.getOutputStream());
return client;
}
public void recieve() {
request = in.nextLine();
System.out.println(request);
}
public void respond(final String message) {
out.print(message);
out.flush();
}
#Override
public void close() throws IOException {
if(!server.isClosed()) {
client = null;
server = null;
}
}
}
Main.class solution that works:
package httpserver;
import java.io.IOException;
import java.net.Socket;
public class Main {
public static void main(String[] args) throws IOException {
HttpServer server = new HttpServer();
Socket client;
while(true) {
client = server.accept();
server.recieve();
server.respond("HTTP/1.0 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n"
+ "<html><body><b>hello..</b></body></html>");
client.close();
}
}
}
Main.class solution that doesn't work:
package httpserver;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try(HttpServer server = new HttpServer()) {
while (true) {
server.accept();
server.recieve();
server.respond("HTTP/1.0 200 OK\r\n"
+ "Content-Type: text/html\r\n"
+ "\r\n"
+ "<html><body><b>hello..</b></body></html>");
}
} catch(IOException ex) {
System.out.println("We have a problem: " + ex.getMessage());
}
}
}
I could imagine it has something to do with not closing the client socket after each loop iteration. But even so, it should at least go through once, before bugging up in that case. I really can't see what the problem is supposed to be.
No error messages, nothing...

You do not specify any Content-length when sending the HTTP, so the browser does not know when to stop reading for more data. See How to know when HTTP-server is done sending data for more info.
In the working example you closed the client socket, which tells the browser there is no more data - for your ambitions this might be enough if you don't want the browser to respond.

Related

Java Client-Server Programming: Shared Memory Between Clients

I am developing a simple 2D multiplayer game in Java, following the Client-Server model. The functionality in terms of the socket programming is simple:
A Client sends the Server their character data (x position, y position, health points, etc.)
The Server registers the updated character data in a table which is storing all the different Clients' character data
The Server sends back the table to the Client so that they can render the other characters
I am running into a weird issue that I would like help understanding so I can move forward with the project. Here is the code I'm running right now.
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Set;
import java.util.Vector;
import java.util.HashSet;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server
{
private static Vector<Integer> IDs = new Vector<>();
public static void main(String[] args) throws Exception
{
ExecutorService pool = Executors.newFixedThreadPool(32);
try (ServerSocket listener = new ServerSocket(40000))
{
System.out.println("The server is up.");
while (true)
{
pool.execute(new Player(listener.accept()));
}
}
}
private static class Player implements Runnable
{
private Socket socket;
private Scanner input;
private PrintWriter output;
private int ID;
public Player(Socket socket)
{
this.socket = socket;
this.ID = IDs.size() + 1;
IDs.add(ID);
}
public void run()
{
try
{
input = new Scanner(socket.getInputStream());
output = new PrintWriter(socket.getOutputStream(), true);
while(input.hasNextLine())
{
String result = "";
for(int i = 0; i < IDs.size(); i++)
{
result += (IDs.get(i) + " ");
}
output.println(result);
}
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("127.0.0.1", 40000)) {
Scanner scanner = new Scanner(System.in);
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (scanner.hasNextLine()) {
out.println(scanner.nextLine());
System.out.println(in.nextLine());
}
in.close();
scanner.close();
}
}
}
What I want to happen is: every time a Client sends any message to the Server, the Server responds with a list of IDs (each Client that connects gets a fresh ID).
What is actually happening:
The second Client that connects is able to see that there is a first Client that is already connected. But the first Client is not able to see that there is a second Client connected.
Thank you for your help.
The server loop
while(input.hasNextLine())
{
String result = "";
for(int i = 0; i < IDs.size(); i++)
{
result += (IDs.get(i) + " ");
}
output.println(result);
}
never calls input.nextLine(), which means that input.hasNextLine() is always true, so the server floods the socket with output until the buffer is full.
This can be seen by starting a client, killing the server, then keep pressing enter. The client keeps receiving data, even though the server is gone, until the buffer is emptied.
Add the following line inside the loop:
System.out.println(this.ID + ": " + input.nextLine());
This will make the server consume the line from the client, as was intended, and allow you to see / verify the data flowing.

Cannot reconnect to bluetooth server without restarting bluetooth radio

I have an android client device that will attempt to connect to a bluetooth-enabled server and transmit data to it. So far, it's been working great except for one hitch: whenever I want to reconnect to the server after the connection was terminated, the server does not detect that a request for connection was sent by the client. If I turn off and on the bluetooth radio, and then attempt to reconnect, everything works normally. What am I doing wrong?
Here's the main Class
package org.team2180.scoutingServer;
import java.io.IOException;
import javax.bluetooth.*;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import org.json.JSONObject;
import javax.bluetooth.UUID;
public class Server {
public static final UUID serviceUUID = new UUID("94f39d297d6d437d973bfba39e49d4ee", false);
public static String connectionString = "btspp://localhost:" + serviceUUID.toString() +";name=ProblemServer";
static LocalDevice locDev;
public static final JSONObject DATA = new JSONObject();
public static void main(String[] args) {
try {
locDev = LocalDevice.getLocalDevice();
System.out.println("Local Device: '" + locDev.getFriendlyName()+"' # "+locDev.getBluetoothAddress());
StreamConnectionNotifier streamConnNot = startServer();
startListening(streamConnNot);
} catch (Exception e) {
e.printStackTrace();
}
}
public static StreamConnectionNotifier startServer() throws Exception {
if(serverStarted){return null;}
boolean isNowDiscoverable = locDev.setDiscoverable(DiscoveryAgent.GIAC);
System.out.println("Local Device Discoverable: "+Boolean.toString(isNowDiscoverable));
System.out.println("Local Device URI: "+connectionString);
StreamConnectionNotifier streamConnNot = (StreamConnectionNotifier) Connector.open(connectionString);
System.out.println("Server: Created, waiting for clients . . . ");
return streamConnNot;
}
public static void startListening(StreamConnectionNotifier streamConnNot) throws IOException {
while(true) {
StreamConnection connection = streamConnNot.acceptAndOpen();
Thread connectedThread = new Thread(new ConnectionHandler(connection, TEAM_DATA));
System.out.println("Sever: found a client, placed on thread:" + connectedThread.getId());
connectedThread.start();
}
}
}
I handle each connection with its own thread based on this Class, exchanging an initial byte to determine how to handle the connection (send data to the device's database, get data from the device's database)
package org.team2180.scoutingServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import javax.microedition.io.StreamConnection;
import javax.bluetooth.RemoteDevice;
import org.json.*;
public class ConnectionHandler implements Runnable {
final StreamConnection connection;
final JSONObject TEAM_DATA;
RemoteDevice remDev;
String deviceIndex;
public ConnectionHandler(StreamConnection connection,JSONObject TEAM_DATA) {
this.connection = connection;
this.TEAM_DATA = TEAM_DATA;
try {
this.remDev = RemoteDevice.getRemoteDevice(connection);
this.deviceIndex = remDev.getFriendlyName(true)+'#'+remDev.getBluetoothAddress();
} catch (IOException e) {
this.remDev = null;
this.deviceIndex = null;
}
}
#Override
public void run() {
try {
OutputStream out = connection.openOutputStream();
InputStream in = connection.openInputStream();
PrintWriter pWriter = new PrintWriter(new OutputStreamWriter(out));
BufferedReader bReader = new BufferedReader(new InputStreamReader(in));
int handshake = in.read();
if(handshake==1) {
System.out.println(deviceIndex+" will now inform you of TOP SECRET_INFO");
updateDatabase(remDev, pWriter, bReader);
System.out.println(deviceIndex+" >\n"+ TEAM_DATA.getJSONObject(deviceIndex).getInt("entryCount"));
}
} catch (Exception e) {
System.out.println(deviceIndex+"'s thread is terminating BADLY!");
try {connection.close();} catch (IOException e1) {e1.printStackTrace();}
return;
}
System.out.println(deviceIndex+"'s thread is terminating!");
return;
}
public void updateDatabase(RemoteDevice remDev, PrintWriter ex, BufferedReader in) throws IOException, JSONException {
//OK!
ex.write(1);
ex.flush();
char[] charData = new char[8192];
in.read(charData);
String data = new String(charData);
connection.close();
//Continue doing other things with data
.
.
.
Here is the Android client code to connect to the server.It is not a thread, and does block, however, this is intentional so that the user waits before leaving the connection radius
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String text = gatherData();
try{
bS = getSockToServer();
bS.connect();
OutputStream bsO = bS.getOutputStream();
InputStream bsI = bS.getInputStream();
bsO.write(1);//Code upload
bsO.flush();
Log.d("sendButton.onClick","sent condition code 1");
int handRespond = (int)bsI.read();
Log.d("recieved",handRespond+"");
if(handRespond == 1){
bsO.write(text.getBytes("UTF-8"));
bsO.flush();
}
}catch(Exception e){
Log.e("sendButton.onClick",e.toString());
try{
bS.close();
}catch(IOException ioE){
Log.e("sendButton.onClick{SNC}",e.toString());
}
}
}
});
My final goal would be to handle multiple devices at once (hence the usage of threads) and not have to reset the radio every time a device needs to reconnect.
My code extremely crude; I have only been working with bluecove (and bluetooth in general) for two weeks. Any advice/tricks are appreciated!
I can't relive i didn't see this before.
I need to close the socket clientside.
Whoops.

objectInputStream.readObject() throws exception java.io.OptionalDataException

Can someone please resolve this issue.
Using JDK 1.8, I am trying to build a very simple chat application in Java using Sockets. In my client class as soon as following line executes
Message returnMessage = (Message) objectInputStream.readObject();
it throws exception.
Exception in thread "main" java.io.OptionalDataException
I am writing only objects of type Message to the stream and reading objects of type Message, since i wrote once, i dont think i am doing anything wrong in reading them in sequence.
Q. Also please let me know what is the best way to debug this type of application, how to hit the breakpoint in server while running client ?
Client
package com.company;
import sun.misc.SharedSecrets;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException{
Socket socket = new Socket("localhost", Server.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String readerInput = bufferedReader.readLine();
String[] readerInputTokens = readerInput.split("\u0020");
if(readerInputTokens.length != 2) {
System.out.println("Usage: Client <integer> <integer>");
} else {
Integer firstNumber = Integer.decode(readerInputTokens[0]);
Integer secondNumber = Integer.decode(readerInputTokens[1]);
Message message = new Message(firstNumber, secondNumber);
objectOutputStream.writeObject(message);
System.out.println("Reading Object .... ");
Message returnMessage = (Message) objectInputStream.readObject();
System.out.println(returnMessage.getResult());
socket.close();
}
}
public static boolean isInteger(String value) {
boolean returnValue = true;
try{Integer.parseInt(value);}
catch (Exception ex){ returnValue = false; }
return returnValue;
}
}
Server
package com.company;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public final static int PORT = 4446;
public static void main(String[] args) throws IOException, ClassNotFoundException {
new Server().runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up & ready for connections ...");
// This while loop is necessary to make this server able to continuously in listning mode
// So that whenever a client tries to connect, it let it connect.
while (true){
Socket socket = serverSocket.accept(); // Server is ready to accept connectiosn;.
// Initialize Server Thread.
new ServerThread(socket).start();
}
}
}
Sever Thread
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket socket = null;
ServerThread(Socket socket){
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeChars("\n");
objectOutputStream.flush();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
multiplyNumbers(message);
System.out.println("Writing: "+message.toString());
objectOutputStream.writeObject(message);
System.out.println("Message Written");
socket.close();
} catch( IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
private void multiplyNumbers(Message message) {
message.setResult(message.getFirstNumber().intValue() * message.getSecondNumber().intValue());
}
}
Message Class
package com.company;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = -72233630512719664L;
Integer firstNumber = null;
Integer secondNumber = null;
Integer result = null;
public Message(Integer firstNumber, Integer secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
public Integer getFirstNumber() {
return this.firstNumber;
}
public Integer getSecondNumber() {
return this.secondNumber;
}
public Integer getResult() {
return this.result;
}
public void setResult(Integer result) {
this.result = result;
}
#Override
public String toString() {
return "Message{" +
"firstNumber=" + firstNumber +
", secondNumber=" + secondNumber +
", result=" + result +
'}';
}
}
objectOutputStream.writeChars("\n");
Why are you writing a newline to an ObjectOutputStream? You're never reading it. Don't do that. Remove this wherever encountered.

String data from a Scanner through a PrintWriter

I am trying to pass data from a String into a PrintWriter while simultaneously reading from a BufferedReader between two classes named Server.java and Client.java. My problem is that I am having trouble handling the exceptions that are being thrown from the block of code that reads data from the Scanner object (marked below).
Client.java
package root;
/**
* #author Noah Teshima
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private Socket clientSocket;
private BufferedReader bufferedReader;
private InputStreamReader inputStreamReader;
private PrintWriter printWriter;
private Scanner scanner;
public static void main(String[] args) {
new Client("localhost", 1025);
}
public Client(String hostName, int portNumber) {
try {
this.clientSocket = new Socket(hostName, portNumber);
this.bufferedReader = new BufferedReader(this.inputStreamReader = new InputStreamReader(this.clientSocket.getInputStream()));
this.printWriter = new PrintWriter(clientSocket.getOutputStream());
String msg = "",
msg2 = "";
this.printWriter.println(this.getClass());
this.printWriter.flush();
System.out.println(this.getClass().getName() + " is connected to " + this.bufferedReader.readLine());
while(!(msg = this.scanner.nextLine()).equals("exit")) { //Source of problem
this.printWriter.println(this.getClass().getName() + ": " + msg);
this.printWriter.flush();
while((msg2 = this.bufferedReader.readLine()) != null) {
System.out.println(msg2);
}
}
this.clientSocket.close();
}catch(IOException exception) {
exception.printStackTrace();
}
}
}
Stack trace::
Exception in thread "main" java.lang.NullPointerException
at root.Client.<init>(Client.java:47)
at root.Client.main(Client.java:25)
The code used to read from the BufferedReader and write to a PrintWriter is the same for both classes, so I only posted Client.java. If anyone would like to see the other class file, I would be happy to do so.
Before you use
while(!(msg = this.scanner.nextLine()).equals("exit")) { //Source of problem
You should have initialized the scanner.
The scanner object is null when you used it, and hence the NullPointerException.
I do not see a scanner = new Scanner(...); anywhere within your code,
maybe you have forgetten about it?

ClassLoader serializable?

I've been trying to make some sort of alpha key system for my game. I thought in order to prevent people from decompiling my jar and changing around some code to bypass the system and get straight into my game, I thought about making it so after some verification, the server would send a serialized copy of a ClassLoader object to the client, which the client can then use to load the required files off an external host to start running the game.
Turns out it's not working at all.. ClassLoader seems to be non-serializeable. Are there any suggestions on how I could make a simliar system, or some way to somehow be able to ram that ClassLoader object through?
Source code:
Server.java:
package org.arno;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.arno.Packet.ClassLoaderPacket;
public class InitServer {
private static ObjectOutputStream out;
private static ObjectInputStream in;
private static ServerSocket server;
private static Socket connection;
private static final float HANDSHAKE_UID = 9678;
public static void main(String[] args) {
startServer();
}
private static void startServer() {
try {
server = new ServerSocket(7799,100);
System.out.println("[LoginServer] Initiated");
while (true) {
waitForClientConnection();
setStreams();
waitForHandShake();
sendData();
closeClientConnection();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void closeClientConnection() throws Exception {
out.close();
in.close();
connection.close();
}
private static void waitForHandShake() throws Exception{
float handshake = (float) in.readObject();
System.out.println(handshake == HANDSHAKE_UID? "Handshakes match UID" : "Wrong handshake sent");
}
private static void sendData() throws Exception {
ClassLoaderPacket.writeObject(new ClassLoaderPacket(out));
System.out.println("DATA SEND");
}
private static void waitForClientConnection() throws Exception {
connection = server.accept();
System.out.println("[LoginServer] Connection made from IP ["
+ connection.getInetAddress().getHostAddress() + "]");
}
private static void setStreams() throws Exception {
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
}
}
ClassLoaderPacket.java:
package org.arno.Packet;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* #author arno
* File: ClassLoaderPacket.java
*/
public class ClassLoaderPacket implements Serializable {
static ObjectOutputStream out;
private transient ClassLoader cL;
private static final String GAME_URL = "https://dl.dropboxusercontent.com/u/9385659/Avalonpk718.jar";
public ClassLoaderPacket(ObjectOutputStream out) throws MalformedURLException {
this.out = out;
cL = new URLClassLoader(new URL[] { new URL(GAME_URL) });
}
public ClassLoader getClassLoaderContext() {
return cL;
}
public static void writeObject(ClassLoaderPacket packet) throws IOException {
out.writeObject(packet.getClassLoaderContext());
}
}
Client sided reading:
public void receiveData() throws Exception {
gameLoader = (ClassLoader) in.readObject();
}
I think there are too much of complex fields in the ClassLoader in order to serialize it. Additionally, it should implement Serializable interface and have serialVersionUID in the serializable class.
Would it be enough just to obfuscate the code? I think there are plenty of tools which may help you to conceal your code.
Here is the useful thread about java code obfuscation/protection: Best Java obfuscator?

Categories

Resources