This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I am creating a an application where a client can send TCP packets to a server and the server will respond.However, when I flush() my buffered data to an outputstream, it produces a nullpointer exception. For each new client that connects, a new thread with a class is created. Here is the class:
public class clientHandler implements Runnable{
private boolean loggedin = false;
private String username = "";
Socket cs;
OutputStream rawoutput; //for some reason I had to pass the outputstream directly to the constructor rather than get it here, here it would produce a npe
clientHandler(Socket clientSocket, OutputStream bos){
rawoutput = bos;
cs = clientSocket;
}
DataOutputStream output;
{
try {
output = new DataOutputStream(rawoutput);
} catch (Exception e) {
System.out.println("rip OS");
e.printStackTrace();
}
}
//a couple more methods...
private void metaData(String data) throws Exception{
if(data.startsWith("/iusername")){
String[] useful = data.split(";");
System.out.println(useful[0].split(":")[1] + " logged in");
output.writeBytes("logged in");
output.flush();
username = useful[0].split(":")[1];
loggedin = true;
}
}
}
I am using netcat as a 'client' until I write my own. Is this perhaps why it causes the NPE? I have tried this all different kinds of outputstreams and writers and they all produce error at either the initialization, the write or the flush.
Thanks to the user John Skeet, I fixed the error. The problem was that I had the output DataOutputStream in an initialization block without realizing it. So to fix I had to just move that to the run() function and now everything works.
Related
I have a server and a client set up in this way. I can't find the cause of the EOFException, because it happens randomly. It throws the following exception every time a client connects, but I can't figure out the source of it. It always occurs before it reads what the client has sent. The exception always is at this line:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Here is the exception:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End$3.run(End.java:62)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
Here is my server code:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
Here is my client code:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
What I've Tried
I've tried to fix this issue many times before. I tried to create object output streams. I've switched the order that I initialize the object input stream and object output stream. This is so that the server doesn't get frozen in a deadlock with the client. I have no idea what could be causing this error.
I think I know what is going on here, but I can't be certain because your code is fragmentary, and the symptoms are not well characterized. (The exceptions are unlikely to really be random, for example.)
First there is one indisputable fact. A one side of a connection sees an EOFException because the other side has closed the network connection. That's what that exception means.
In your case, the server gets the exception in the ObjectInputStream constructor because the constructor attempts to read an object stream header that the client side never sends ... on that connection.
Now, the theory. I think I know why. Here is the relevant part of your code (with some bits snipped out for brevity).
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
Notice that there are two sockets! The first one is created and passed to the shutdown hook. The second one is created and used within send and then closed.
I think the problem is the first Socket. When that is created, it establishes a connection to the server. The server code will accept it and then attempt to read. The read will block ... since the client side hasn't written anything to that socket. The client will then call send which opens and uses a different Socket.
Eventually, the client application exits.
When it exits, the shutdown hook closes the first socket. That causes the server side to see the end of stream ... and triggers the EOFException.
So how to fix this?
It rather depends on the "big picture". Is the real client sending a single message to the server, or does it need to reuse the socket to send multiple messages?
Assuming the former, the solution is simple:
Get rid of the code that creates a socket and passes it to a shutdown hook. As you have written it, it serves no useful purpose.
Rewrite the send method to use try with resources; e.g.
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
Note that the above will automatically close the 3 resources in the correct order.
This question already has answers here:
Java socket, Is that a dead lock or what?
(2 answers)
Must server & client have reverse sequence of claiming ObjectOutputStream & ObjectInputStream?
(1 answer)
Closed 4 years ago.
I am working on a Java Client/Server that will communicate via String commands. The Server is near complete, but the Client freezes when creating the ObjectInputStream from the server. I have tried changing the I/O Streams on the server a few different ways, but no matter what I do I end up with the program freezing on the same line.
Server code:
public class Server {
//a lot of other methods
public void launchServer(){
// Text area for displaying server console
TextArea ta = new TextArea();
// Create a scene and place it in the stage
Stage console = new Stage();
Scene scene = new Scene(new ScrollPane(ta), 450, 200);
console.setTitle("Server"); // Set the stage title
console.setScene(scene); // Place the scene in the stage
console.show(); // Display the stage
new Thread( () -> {
ServerSocket serverSocket = null; Socket socket = null;
ObjectInputStream fromClient = null; ObjectOutputStream toClient = null;
Platform.runLater( () -> {
ta.appendText("Server started at " + new Date() + '\n');
});
// Create a server socket
try{
serverSocket = new ServerSocket(8000);
while (true) {
socket = serverSocket.accept();
Platform.runLater( () -> {
ta.appendText("Thread started at " + new Date() + '\n');
});
new MyThread(socket).start();
}
}
catch(IOException e){e.printStackTrace();}
}).start();
}
}
MyThread:
class MyThread extends Thread{
protected Socket socket;
private String command;
ObjectInputStream fromClient = null;
ObjectOutputStream toClient = null;
Homework6French schoolServer;
Connection connection = schoolServer.connection;
public MyThread(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
try {
// Create data input and output streams
fromClient = new ObjectInputStream(socket.getInputStream());
toClient = new ObjectOutputStream(socket.getOutputStream());
while (true) {
//read the command from the client
command = (String) fromClient.readObject();
//read the first word of the command, and cut it out of the command
String comStart = command.substring(0, 3);
command = command.substring(4);
//run method based on what first word of command was
switch(comStart){
case "GGr":
getGrade(); break;
case "GSt":
getStudents(); break;
case "GCo":
getCourses(); break;
default:
toClient.writeChars("Command not recognized"); break;
}
}
}
catch(IOException e){e.printStackTrace();}
catch(ClassNotFoundException e){e.printStackTrace();}
finally{
try{
fromClient.close();
toClient.close();
}
catch(Exception e){e.printStackTrace();}
}
}
}
Client:
public class Client {
//member data
ObjectOutputStream toServer = null;
ObjectInputStream fromServer = null;
public void start(Stage primaryStage) {
//...
try {
// Create a socket to connect to the server
Socket socket = new Socket("localhost", 8000);
System.out.println("socket made");
// Create an input stream to receive data from the server
fromServer = new ObjectInputStream(socket.getInputStream());
System.out.println("fromSerrver made");
// Create an output stream to send data to the server
toServer = new ObjectOutputStream(socket.getOutputStream());
System.out.println("toServer made");
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
Server works fine on its own, Client launches okay and gets as far as printing "socket made", then gets stuck. Also of note is that before the try statement in the Client code, a JavaFX Stage is defined and created, and the window appears but the buttons never appear in the window.
I thought that perhaps I needed to have I/O Streams defined inside MyThread and before MyThread is called, but if I try to create an InputStream before the socket is accepted a NullPointerException is thrown. How can I understand why this InputStream freezes the client?
You must create and flush the ObjectOutputStream first, before the ObjectInputStream, at at least one end. The safe way to ensure that is do it at both ends.
The reason is that the object output stream creates a stream header when constructed, and the object input stream reads it when constructed. So if both object input streams are constructed first, you deadlock.
if I try to create an InputStream before the socket is accepted a NullPointerException is thrown.
Of course it is. The Socket variable is still null. I don't know why you even tried it, or mention it here.
I have written a Java Chat Server program.
This is a simple standalone program for Server.
I have to run this then run Client to get Chat working.
What are some possible Unit Test scenarios for the server program? Can anyone show me some example of unit test based on this code?
I have never written a unit test code before and I can't really think of what needs to be tested here.. I think testing Connection can be one but what else? (and how to?)
public class SimpleChatServer {
static final Logger logger = LogManager.getLogger(SimpleChatServer.class);
ArrayList<PrintWriter> clientOutputStreams;
private BufferedReader reader;
private Socket sock;
private ServerSocket serverSock;
public class ClientHandler implements Runnable{
public ClientHandler(Socket clientSocket){ // Socket Connection
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch(Exception ex) {
logger.trace(ex);
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read " + message);
tellEveryone(message);
}
} catch(Exception ex) {
logger.trace(ex);
}
} //close run
} //close ClientHandler
public static void main (String[] args) throws Exception
{
new SimpleChatServer().listen();
}
#SuppressWarnings("resource")
public void listen()
{
clientOutputStreams = new ArrayList<PrintWriter>();
try {
ServerSocket serverSock = new ServerSocket(8000); //port number 8000 was used
while(true) {
Socket clientSocket = serverSock.accept();
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
}
} catch (Exception ex) {
logger.trace("Server Error", ex);
} finally {
try
{
serverSock.close();
}
catch(Exception e){}
}
} // close go
public void tellEveryone(String message)
{
Iterator<PrintWriter> it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception ex) {
logger.trace(ex);
}
} // end while
} // close tellEveryone
}
I was going to crib an answer from Pragmatic Unit Testing, but suggest you just find a copy. At the very least you should consider whether results are right, whether your boundary conditions are correct, and if you can force error conditions.
Testing results often means making sure combinations of input get the expected results. Boundaries are reflected in the related "0, 1, many" rule, where you do silly stuff to see if your code has implicit boundaries that can be reached with bad, null or unexpected values.
For example, what happens if you pass huge Strings to your methods that take them? What about strings with weird Unicode chars in them? No line breaks?
Forcing error conditions means making sure things degrade gracefully and/or throw under the expected situation.
Think about your code as a brittle little appliance and then pretend a poo-flinging monkey, a 14-yr old hacker and your non-hacker grandmother (I know some exist) are all taking turns on it.
EDIT: I have corrected the mistake below in the code, by adding a line into the server code
I'm trying to write some socket code that will allow me to send data from one computer to another for a game (which for simplicity's sake, we can think of as tic-tac-toe, not much data needs to be sent, just a couple of numbers). In order to achieve this I have written two classes, Server and Client. At the moment I am testing through the localhost using port 1234, and I am only using one single instance of the program (though the same problem occurs when trying to use two instances).
Firstly here's the code, and then I can go into more depth about the problem, and what testing I've done to attempt to work out what is going wrong:
public class Server
{
private ServerSocket server;
private Socket socket;
private Client socketHandler;
private static final int DEFAULT_PORT = 1234;
public Server() { this(DEFAULT_PORT); }
public Server(int port)
{
Thread thread = new Thread()
{
public void run()
{
try
{
System.out.println("Attempting to Establish Connection");
server = new ServerSocket(port);
socket = server.accept();
socketHandler = new Client(port, socket); //THIS LINE ADDED
System.out.println("Server Online!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
//ADJUSTED
Client getSocketHandler()
{
return socketHandler;
}
public void kill()
{
try
{
if (socket != null) socket.close();
if (server != null) server.close();
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
socket = null;
server = null;
}
}
}
public class Client
{
public static final int DEFAULT_PORT = 1234;
public static final String DEFAULT_HOST = "localhost";
private static final String THUMP_THUMP = "thump thump";
private static final int PULSE = 1000;
private int port;
private String ip;
private Socket socket;
private BufferedReader input = null;
private PrintWriter output = null;
boolean closed = true;
String data = "";
public Client() { this(DEFAULT_PORT, DEFAULT_HOST, null); }
public Client(int port) { this(port, DEFAULT_HOST, null); }
public Client(int port, String ip) { this(port, ip, null); }
public Client(int port, Socket server) { this(port, DEFAULT_HOST, server); }
public Client(String ip) { this(DEFAULT_PORT, ip, null); }
public Client(String ip, Socket server) { this(DEFAULT_PORT, ip, server); }
public Client(Socket server) { this(DEFAULT_PORT, DEFAULT_HOST, server); }
public Client(int port, String ip, Socket server)
{
socket = server;
this.ip = ip;
this.port = port;
Thread thread = new Thread()
{
public void run()
{
try
{
initialise(server);
String line;
startHeartbeat();
while (isClosed()) {} //first it is closed, lets wait for it to open before we start waiting for it to close!
System.out.println("We are about to listen!");
while (!isClosed())
{
System.out.println("pre-read"); //this line was used to determine that the code was hanging on the next line
line = input.readLine(); //offending line
System.out.println("post-read"); //this line was used to determine when the block was lifted
if (line != null)// || line != THUMP_THUMP)
{
System.out.println(line);
data += line + "\n";
}
}
System.out.println(data);
kill();
System.out.println("Connection Closed!");
}
catch (SocketException e)
{
e.printStackTrace();
System.out.println("Server closed!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
thread.setDaemon(true);
thread.start();
}
private void initialise(Socket server)
{
try
{
if (server == null) socket = new Socket(ip, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
}
catch (IOException e) { e.printStackTrace(); }
}
public boolean post(String text)
{
synchronized(this)
{
output.println(text);
output.flush();
return !output.checkError();
}
}
public void kill()
{
try
{
if (input != null) input.close();
if (socket != null) socket.close();
}
catch(IOException e) { e.printStackTrace(); }
finally
{
input = null;
socket = null;
}
}
public void killOutputStream()
{
try
{
if (output != null) output.close();
}
catch (Exception e) { e.printStackTrace(); }
finally
{
output = null;
}
}
//////////////////////////////////
///////// Socket Control /////////
//////////////////////////////////
synchronized boolean isClosed()
{
return closed;
}
synchronized void setClosed(boolean b)
{
closed = b;
}
//We need to make sure that the socket is still online, to ensure the reading stops when the connection closes.
void startHeartbeat()
{
Thread heartbeat = new Thread()
{
public void run()
{
while (output != null)
{
setClosed(post(THUMP_THUMP) ? false : true); //post returns true on success
synchronized(this)
{
try
{
this.wait(PULSE);
}
catch (InterruptedException e) {}
}
}
setClosed(true);
}
};
heartbeat.setDaemon(true);
heartbeat.start();
}
}
The Problem
When the client is started (after having created the server) it fails to read any data sent through (or even the heartbeat), in fact the code does not go past line = input.readLine() in the reading thread (which is from now on called the offending line), except it seems, until the server is disconnected (see below).
Here is the order of regular testing:
Server() is called and the resulting Server is stored in the serverConnection variable then
Client(serverConnection != null ? serverConnection.getSocket() : null) is called and the new Client is stored in clientConnection.
Because we can test whether it is working using the heartbeat no other data needs to be sent, and the server is terminated by calling serverConnection.kill() and then clientConnection.killOutputStream() after letting some time elapse.
and this is the result:
Attempting to Establish Connection Server Online!
We are about to listen!
Connection Closed!
where the empty line represents the non null data received over the course of the connection, ie that there is none.
I expect this:
Attempting to Establish Connection
Server Online!
We are about to listen!
thump thump
thump thump
thump thump (and so on, every second)
Connection closed!
I spent time performing different tests by commenting out or changing the code slightly with the same testing format (except for the special case, which is number 6) and made these observations:
Observations
Only when the socket is closed and the output stream is closed, does the program move past the offending line.
When the readline() method starts to process (shortly before the heartbeat cuts it off) it detects nothing in the stream, not even THUMP_THUMP.
When the socket is closed, but the output stream is not, the readline() method starts to process, only to detect nothing, heartbeat cuts it off. No SocketException even though it would be expected.
If the socket is NOT closed, and only the output stream is closed, a SocketException is triggered, suggesting the socket is closed.
I used netstat -an in command prompt, and when the server is started the port 1234 is LISTENING. When the client connects, it is still LISTENING, implying that there is no connection.
I set up some python code to connect to itself over port 1234,
however I made a mistake in the python code, and as such the server
didn't close, and was still open. So I decided to connect the java
client to the server and see what happens. I did this by running
Client(null) which is the client code for the non-host. It
resulted in the port reading ESTABLISHED, and the python server was
echoing back the "thump thump", and the java code was successfully
reading it. No hanging, it worked perfectly.
This leads me to believe that the problem lies in the server code, as the python server was able to communicate sucessfully with the Java client, but the Java client is unable to communicate with the Java server.
Before performing this testing I had been concentrating on the Client code, believing that it was at fault. All the questions I have found here with similar symptoms (see here, here and here, among others) have turned up blank for me, having written in their solutions (most were due to the output stream not flushing, or the \n ommitted, which I have not failed to do, or the solution not fixing my problem, and so having been removed in favor of the heartbeat in this case). I originally based my code off of this article.
After 4 days of trying to figure out this problem I am at a loss for what to do... What am I missing here? Why is the Server code not working as I expect it to? If anybody needs any more clarification on my code then please ask!
As an after-note, the testing code is run through a simple minimalistic GUI written in javafx (not fxml though), whether that would be a problem or not I'm sure, I would think not, due to it working with the Python server. This code is compiled in Java 8
I'm a little confused about why you think it would go any furthur than input.readLine() considering there is no handling of inputs/outputs on the server side....
Client/Server connections are like a game of tennis, as one side serves the other must receive the ball and then serve it back(maybe with different information). Your server side must handle the input it recieves from the start heartbeat method, and then send you back a response. the input.readLine() function blocks the thread until it receives data from the other end, so yes the code stops there and waits for your server to send the "tennis ball" back. In the server class you should add an input and output stream that handle the heart beat inputs and send back a string of data to the client.
Server:
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String response = "thump thump";
while(true){
is.read();
os.write(response.getBytes());
os.flush();
}
with this example, the client should remain unchanged and just add the above code to your server.
I'd really appreciate some help with my program
Exception in thread "Thread-4" java.lang.NullPointerException
at ServerConnect.replyChoice(BaseStaInstance.java:63)
at ServerConnect.run(BaseStaInstance.java:45)
at java.lang.Thread.run(Thread.java:619)
my ServerConnect function looks like :-
class ServerConnect extends Thread {
Socket skt;
String sProcessId;
ServerConnect scnt = null;
ObjectOutputStream myOutput;
ObjectInputStream myInput;
ServerConnect(){}
ServerConnect(Socket connection, String sProcessNo) {
this.skt = connection;
this.sProcessId = sProcessNo;
}
public void run() {
try {
myInput = new ObjectInputStream(skt.getInputStream());
ServerConnect scnt = new ServerConnect();
while(true) {
try{
int ownTimeStamp = Global.iTimeStamp;
Object buf = myInput.readObject();
//if we got input, print it out and write a message back to the remote client...
if(buf != null){
LINE 45--> **scnt.replyChoice(buf);**
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
void replyChoice(Object buf){
try{
LINE 63 --> **myOutput = new ObjectOutputStream(skt.getOutputStream());**
System.out.println("Server read:[ "+buf+" ]");
myOutput.writeObject("got it");
myOutput.flush();
}catch(IOException e){
e.printStackTrace();
}
}
}
Its basically a socket programming and multithreaded application. On executing it on different terminals inorder to have the client and server establish connections, I execute my code. But it throws up the error above on both terminals. Its just got something to do with my declaring the myOutput variable at the wrong place. Could someone help me out.
From the error message, I've highlighted line 63 and line 45 in the piece of code attached.
Drop the default constructor
Make your instance fields (stk and sProrcessId) final
See how your compiler complains and fix those issues
These instructons help you trading runtime errors like your NPE to compile time errors, which is the best thing you can do. Note: This trick is meant to be used in general.
Your object is being initialised with the first constructor, which takes no parameters. As a result, skt is never initialised and is therefore null. When you call skt.getOutputStream(), it throws a null pointer exception because it cannot dereference skt.
ServerConnect(){}
ServerConnect(Socket connection, String sProcessNo) {
this.skt = connection;
this.sProcessId = sProcessNo;
}
what constructor do you use ? cause skt might be uninitialised
//Edit : oh i see now you use the wrong constructor
ServerConnect scnt = new ServerConnect();
to
ServerConnect scnt = new ServerConnect(skt,sProcessId);