Just to give the background of my issue; I'm writing a client server application. when a client initially connects, the server accesses the database and send all the items in a particular table to the client by writing the objects to an objectoutputstream in a for loop.
The issue is, the client reads only the first object that is being sent. Even if I create a new object and send it to the server for verification the client does not pick it up when the server sends it back after inserting to database... extract from code:
Server:
public void loadClients()
{
ArrayList <Client> list = dBCon.loadClients();
try
{
for (int i =0; i<list.size();i++)
{
sendtoClient(list.get(i));
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void sendtoClient(Object obj) throws IOException
{
_out.writeObject(obj);
_out.flush();
_out.reset();
}
Client:
socket = new Socket("localhost", 4447);
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
Object objIn = ois.readObject();
Client client = (Client)objIn;
switch(client.actionType)
{
case ("ADD"):
{
if(clientFrame.tbDeals!=null)
{
clientFrame.tbDeals.addClient(client);
break;
}
else
{
clientList.add(client);
System.out.println(client.clientName);
break;
}
}
}
Edit: I have tried with a while loop on the client side as well. then ois.available() returns 0....
You're reading exactly one object on the client side. That's all you're going to get.
available() is rarely if ever used when doing basic IO in Java, and generally isn't going to do what you think it does.
Reading from a ObjectInputStream is blocking, just like all other basic Java IO. Using readObject() you will either get an object, or an exception as noted in the javadoc
The most simplistic example of how you would handle this in a loop if you have no idea the number of objects you'll be receiving and expect the connection to stay open is:
while (true) {
try {
Object o = ois.readObject();
/// do something with the object you just read
} catch ( EOFException e) {
System.out.println("remote connection closed!");
e.printStackTrace();
break;
}
}
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.
I want to send an object from my client to my localhost server to add to database, and send result back whether the object was sent successfully or not. The object was sent successfully, but my server doesn't send the result back to client, and causes my client frame form hanged due to waiting for response from server. I don't know what's wrong with my code. Can you tell me some ways to fix this?
Here is the function to send the result:
public void sendResult(String result) {
try {
Socket clientSocket = myServer.accept();
System.out.println("Connected to client");
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
os.writeObject(result);
System.out.println("Result sent");
} catch (Exception ex) {
ex.printStackTrace();
}
}
Where the send result function is called:
public void service() {
try {
if (receiveStudent() != null) {
Student std = receiveStudent();
if (dao.addStudent(std)) {
System.out.println("OK");
sendResult("OK");
} else {
System.out.println("FAILED");
sendResult("FAILED");
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
In addition, in the Service function, the console printed "OK", which means the if condition was satisfied.
receive student method:
public Student receiveStudent() {
Student s = new Student();
try {
Socket clientSocket = myServer.accept();
System.out.println("Connect to client successfully");
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
Object o = ois.readObject();
if (o instanceof Student) {
s = (Student) o;
return s;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
Because of myServer.accept() in sendResult(), the server is again waiting for an incoming client connection while this already happened in receiveStudent(). Reuse that connection.
Share the client socket you've obtained in receiveStudent() by, e.g., turning it into a field.
public Student receiveStudent() {
...
try {
clientSocket = myServer.accept();
...
} catch (Exception ex) {
...
}
...
}
and then reuse that socket in sendResult() to send the result to the client.
public static void sendResult(String result) {
try {
...
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
...
} catch (Exception ex) {
...
}
}
If you want to send a String as object why don't you just use something like this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); //for sending String messages
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); //for getting String messages
... and then when you need to send you do it like this:
out.println(textToServer"); // send to server - don't forget LN in println.
out.flush(); // to clean buffer
It should do what you need to be done.
And make sure that your client class is waiting to get that InputStream you're sending, don't forget that, since maybe it's the problem in the Client side.
Maybe Client is not accepting that incoming Socket regardless if it's ObjectInputStream or BufferedReader that will accept the incoming socket object.
You could provide us a Client class so we can see if there's missing acceptance of incoming socket.
At the end of the method make sure you close your streams and sockets.
out.close();
in.close();
socket.close();
For more details check this, this and this. I hope I was helpful :)
You're calling accept() twice. This is meaningless. You need to:
Accept the connection. This returns a Socket.
Read the request and create the response.
Send the response, via the same Socket you accepted at (1).
You also want to create a new thread per accepted socket, and you also want to do all I/O in that thread, including creating the ObjectInputStream and ObjectOutputStream. Otherwise your server isn't properly multi-threaded and multi-client.
I'm now creating a simple TicTacToe game on Android phone.
I used java server to handle multiplayer part, but when I pair the players and 'new' the ObjectInputStream, it throw me the exception.
java.io.StreamCorruptedException: invalid stream header: 74001057
These is my server code when create a new game thread:
public GameThread(Socket Player1, Socket Player2) {
this.Player1 = Player1;
this.Player2 = Player2;
System.out.println("GameThread Started!");
//Exception throw at the codes below
new ReceiveMessagesThread(this.Player1, this.Player2).start();
new ReceiveMessagesThread(this.Player2, this.Player1).start();
}
These is my server codes for receiving message in a game thread:
// This is an inner class.
private class ReceiveMessagesThread extends Thread {
private Socket SourceClient, DestinationClient;
ReceiveMessagesThread(Socket SourceClient, Socket DestinationClient) {
this.SourceClient = SourceClient;
this.DestinationClient = DestinationClient;
}
#Override
public void run() {
while (true) {
try {
// Exception throw at the line below
ObjectInputStream in = new ObjectInputStream(this.SourceClient.getInputStream());
switch (in.readByte()) {
case ServerGlobal.BOARD_STATUS:
GameBoard = (char[][]) in.readObject();
SendBoardStatus(this.DestinationClient);
break;
}
}
catch (java.io.StreamCorruptedException ex) {
ex.printStackTrace();
break;
}
catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(GameThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Move the creation of the ObjectInputStream ahead of the loop. It tries to read a stream header placed there by the peer's ObjectInputStream, which you should likewise only create once. These streams should persist for the life of the socket, not be created anew for each send or receive.
If you output the array of chars into ObjectOutputStream by separate chars, then you should read it also by chars, not as an array.
Also, check for consistent usage of ObjectOutputStream and ObjectInputStream. In your code on github you use DataInputStream in some places.
Also ensure that every wrapping of socket.getInputStream() with new ObjectInputStream() matches corresponding unwrapping of socket.getOutputStream() with new ObjectOutputStream(). Or better yet, wrap the socket streams in ObjectInputStream and ObjectOutputStream only once, not every time you want to read/write something.
I'm attempting to move my networking over from standard IO to NIO and following the few tutorials that there are to attempt to figure it out, while me, myself, and I decided it'd be a great idea to spend my first week rewriting the core for all of the applications logic handling, I never would have imagined that I wouldn't be able to set up the basic networking.
Currently the networking is at a very basic stage, everything is tossed inside of a while-loop and I can't honestly say I've put any attempt into it to make it look nice, considering I haven't a clue what I'm doing my goal was to figure out how to do it first, then go back and give it a makeover.
Here's the code I use to initialize my server:
// Initializes the TCP Server and all of its components.
private void initTcpServer(int port) {
try {
// Create a new selector
Selector socketSelector = SelectorProvider.provider()
.openSelector();
// Create a new non-blocking server socket channel;
this.serverSocketChannel = ServerSocketChannel.open();
this.serverSocketChannel.configureBlocking(false);
// Bind the server socket to the specified address and port
this.serverSocketChannel.socket().bind(
new InetSocketAddress("127.0.0.1", port));
// Register the server socket channel, indicating an interest in
// accepting new connections
this.serverSocketChannel.register(socketSelector,
SelectionKey.OP_ACCEPT);
// Set the selector for the server instance.
this.selector = socketSelector;
} catch (IOException e) {
e.printStackTrace();
}
}
Then this class implements the Runnable interface, and a new thread is started directly after this method completes, in this thread we contain the following code:
public void run() {
while (isRunning) {
try {
selector.selectNow();
} catch (IOException io) {
return;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (!key.isValid()) {
it.remove();
continue;
}
try {
if (key.isAcceptable()) {
this.handleConnection(key);
} else if (key.isReadable()) {
Connection connection = (Connection) key.attachment();
if (connection != null) {
try {
connection.getMasterProtocol()
.decode(connection,
connection.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
} finally {
it.remove();
}
}
}
}
This, from my understanding is what allows us to handle our connections and data based off of a SelectionKey.. and is what all of the NIO based networking runs from, you'll see that I'm calling two different methods to make this not so much of a mess, the first one is #handleConnection and the other one is a decode function.
The handle connection method creates a new instance of my Connection class and attatches it to the SelectionKey, like so:
public Connection(SelectionKey key) {
try {
// For an accept to be pending the channel must be a server socket channel.
ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
// Accept the connection and make it non-blocking.
this.socketChannel = serverSocketChannel.accept();
this.socketChannel.configureBlocking(false);
// Set up other user data.
this.inputStream = new DataInputStream(socketChannel.socket().getInputStream());
this.masterProtocol = new MasterProtocol();
// Register the new SocketChannel with our Selector, indicating
// we'd like to be notified when there's data waiting to be read.
key = this.socketChannel.register(OGServer.getInstance().getSelector(), SelectionKey.OP_READ);
key.attach(this);
// Add the current <SelectorKey, Connection> to the current connections collection.
connections.put(key, this);
Log.debug(getClass(), "Connection constructed successfully.");
} catch(IOException e) {
e.printStackTrace();
}
}
The error is called when I attempt to call the MasterProtocol#decode method, which looks like this:
public Object decode(Connection connection, DataInputStream dataInputStream) throws IOException {
if(connection.getState() == ConnectionState.CONNECTED) {
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
if(bytes.length < 4) {
System.out.println("Not enough bytes read.");
return null;
}
int bufferSize = dataInputStream.readInt();
System.out.println("Buffer Size: " + bufferSize);
while(bytes.length < bufferSize) {
return null;
}
int test = dataInputStream.readInt();
System.out.println("Test: " + test);
return null;
}
return null;
}
The error seems to be called when the DataInputStream tries to read from the network, more specifically on this line of code:
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
The error:
Exception in thread "Thread-0" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:190)
at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
at java.io.DataInputStream.read(DataInputStream.java:100)
at com.google.common.io.ByteStreams.copy(ByteStreams.java:70)
at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:115)
at net.ogserver.framework.net.protocol.MasterProtocol.decode(MasterProtocol.java:29)
at net.ogserver.framework.net.OGServer.run(OGServer.java:146)
at java.lang.Thread.run(Thread.java:745)
The 'IllegalBlockingModeException' exception is what's throwing me off, as all of the information I've found was for setting up a Non-blocking server, but the DataInputStream implementation was my own, so I must have done something wrong somewhere. NIO is a completely different world from IO, but learning is learning, eh?
EDIT: I guess it'd help to know how I'm sending the data from the client, it's just a very basic test application that does this:
socket = new Socket("127.0.0.1", 5055);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBoolean(false);
If you're moving to NIO in non-blocking you can't keep using streams. If you want to use streams there is no advantage to using NIO at all. I would just stop the migration project now.
I tried everything stack overflow has to offer on this common readLine problem. (sending \n, flushing out, changing to byte array style, becoming hermit, wrists )
I suspect in this case its a concurrency thing as Ispent well over 15 hours yesterday confirming that the only thing that isnt working is readline()!
I used loads of other versions like datareader with a byte array and making sure a \n got sent I even sent /ns just in case!
still my issue is the same, and I have ran out of ideas myself to solve the issue and have decided that somewhere, my problem is outside my understanding, just where? its got to be threading right?
I managed to get to read the socket to string that seemed to work so it IS blocking because reading the connection isnt working at all, the readline function is not the only way Ive had it as I said so in my snippets its not as developed as it has been but still the basic issue remains.
Please help, i dont know what the issue is
// So the main class initialises the socket objects and starts them in a thread, these work I get all sorts of flags letting me know that they are
void start_sockets() {
//if this is initiialised as a server and not a client
if (is_server) {
while (is_server) {
try {
System.out.println("listening for connection");
Sockject sj = new Sockject(server.accept());
sock_arr.add(sj);
System.out.println("server made connection ");
// once the connection is made the objects is started in a
// separate thread
new Thread(sock_arr.get(sock_arr.size() - 1)).start();
} catch (IOException e) {
}
}
} else { //else im running a client version of this class
// if the client socket isnt running in a thread, make it run
if (!running) {
new Thread(sj_client).start();
if (sj_client.sock.isConnected()) {
System.out.println("client thread connected to "
+ sj_client.sock.getLocalSocketAddress());
running = true;
}
}
}
}
//the inner class creates a socket object and puts it on an array or an object depending if the parent class is initialised to be a server or a client
class Sockject implements Runnable {
PrintWriter out;
BufferedReader in;
// a socket for processing
Socket sock;
// the constructor in this case initialises the input and output streams
Sockject(Socket s) {
sock = s;
try {
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new InputStreamReader(
this.sock.getInputStream()));
} catch (IOException e) {
close sockets
}
}
//tried variasions of this and similar, used data objects and been sennding /ns all over the shop
void recieve_data() throws IOException {
if (sock.isConnected()) {
if ((recieve = in.readLine()) != null) {
System.out.println("recieve says " + recieve);
}
}
}
// sends data to connection if it is cleared to send data
void send_data(String data) {
// send data called
if (clear_to_send == true) {
out.print(data);
out.flush();
clear_to_send = false;
}
}
#Override
public void run() {
while (threadloop ) {
try {
//code defo gets this far and with just send it keeps running forever so its defo recieve data thats the issue
send_data(send);
recieve_data();// <---I HATE YOU
} catch (IOException e) {
}
}
}
}
}
Now all of the above is ran in an instance of this class, in a thread of this class here these temporary functions are ran and are neversuccesfull
void servrecievex(){
System.out.println("NEVER GETS THIS FA THOUGH DOES IT");
for(int a = 0; a < net_flow.sock_arr.size(); a++){
if(net_flow.sock_arr.get(a).sock.isConnected()){
System.out.println("server recieve function");
net_flow.sj_client.clear_to_send = true;
net_flow.sock_arr.get(a).send_data("www /n \n");
System.out.println("RECIVEIFY!!!");
}
}
}
void clientsendx() {
net_flow.sj_client.clear_to_send = true;
net_flow.sj_client.send_data(Integer.toString(player1.posx) + "\n");
System.out.println("client sent stuff");
}