Client / server communication using serialized objects - java

I try to establish a client / server connection for a mastermind game.
I though of using enumerations to represent the different pegs and made them serializable.
Then I have to implement the connection, using serversocket and getting the socket using accept and so on.
Once the connection is established, I first have to read for client objects, and it is where I am having problems...
Here is a piece of my code, which produces EOFException before I could ever do anything!
(the client data is send on user's interaction).
ObjectInputStream ois =
new ObjectInputStream(socket.getInputStream());
ArrayList<Peg> combination = new ArrayList<Peg>();
do
{
combination.clear();
for (int i = 0; i < 4; i++)
{
combination.add((Peg)ois.readObject());
}
}
while (!checkCombination(combination));
ois.close();
socket.close();
Thank's in advance

We need more details. How are you syncing up writes from the client and the reads on the server? Can you post more details?
BTW, is using raw sockets an absolute requirement? If not, try out RMI which does what you want to do with much less hassle (i.e. sending across Java objects transparently and much more).

If you are getting an EOFException it means the other end has closed the connection.
If you want to send a list, just send the list. i.e.
// on the sender
List<Peg> list =
oos.writeObject(list);
// on the receiver
List<Peg> list = (List<Peg>) oid.readObject();

Related

I Can't Send objects over sockets in Java

I have this problem, and I can't figure it out whats is wrong. I have searched on all over the internet, but without success.
So, I have to send an object over sockets in Java, and I can't figure out how to do it. I tried so many ways. I serialized the object, I tried to write the object directly. But nothing seems to work.
The detail is that I have a chat running in parallel. And sometimes when i open an ObjectOutputStream, or ObjectInputStream, I get busted in a deadlock. And I guess you guys could help me.
Its a hangman game where the clients connects to the server, and the server should send a random word, which is a object, to clients.
Server:
try{
socketConexao = socketRecepcao.accept();
toClient = new DataOutputStream(socketConexao.getOutputStream());
fromClient = new BufferedReader(new InputStreamReader(socketConexao.getInputStream()));
//starts the chat
Thread chat = new Thread(this);
chat.start();
}catch(IOException e){}
//i dont really know how to send the object
try{
byte[] bytes = serialize(palavraSorteada);
toClient.write(bytes);
} catch (IOException e){
e.printStackTrace();
}
Client:
socketCliente = new Socket(ip, port);
toServer = new DataOutputStream(socketCliente.getOutputStream());
fromServer = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
// starts the chat
Thread chat = new Thread(this);
chat.start();
}catch(IOException e){System.exit (0);}
// and dont really know how to receive the object
try{
ObjectInputStream os = new ObjectInputStream(socket.getInputStream());
palavraSorteada = (Palavra) os.readObject();
os.close();
}catch(Exception e){
e.printStackTrace();
}
It should be fairly obvious what wrong here (from your description): You use one communication channel to send two different kinds of data. Since the receiving end can not predict what its going to receive you need to add information what comming next, so the receiving end knows what to do.
And probably noone is going to the trouble to figure out what your code fragments are really doing, reduce the fluff to what you want to ask about or even better make a one class copy&pasteable runnable example (as short as possible) that demonstrates the issue.
In Server, split class Server in Server (accepts connections) and ServerConnection (separate thread). Place variables toClient and fromClient into ServerConnection. Now you spoil that variables when new client connects.
In Client, no need to start new Thread.

Expanding my Java program to send a alert message to other computers

I've written a java intake program that send an PDF-formatted intake to a shared folder so that other people in the network can read it. However, there is not a way for the other people to know that an intake was sent unless someone tells them, so I want the program to send an alert message to the other computers telling them that an intake has been sent.
Now I've done some research into this and figured that TCP is the way to go since it's reliable. I also know that this is a one-to-many sending going on, so I assume that my Intake program will act as the server an the other computers will be the client, or should it be the other way around?
Now I assume that I have to create a client program that listens to the server and waits for it to send a message.
With that in mind, how do I:
Create a client program that listens for the message continuously until the program is closed. I assume that I'll be using "while (true)" and sleep. If so, how long do I put the program to sleep?
Make it as part of Windows service so that can load up when Windows start.
On the server end, how do I:
Send messages to more than one computer, since TCP is not capable of multicasting or broadcasting. I assume an array/vector will play a part here.
Oh, this is a one-way communication. The client doesn't have to respond back to the server.
First of all, UDP is quite reliable (in fact, as reliable as the IP protocol itself). TCP simply ensures that the data was received which involved quite a lot of magic in the back end. Unless you absolutely need to be sure that other machines got the message, you could do it with UDP. Mind that I'm not saying “Don't use TCP”, I just want to make it straight that you should take UDP into consideration as well.
Anyway, yes, you can create a simple listening program. Here is an example of a client in Java that reads messages from the server. It overrides the run method of a Thread class:
public void run() {
try {
String messageFromServer = reader.readLine();
while (messageFromServer != null) {
// Do things with messageFromServer here
// processor.processFromServer(messageFromServer);
messageFromServer = reader.readLine(); // Blocks the loop, waits for message
}
}
catch (IOException e) {
// Handle your exception
}
}
Amongst other things, my thread was set up as such:
public CommunicationThread(String hostname, int port, int timeout) throws IOException, SocketTimeoutException {
InetSocketAddress address = new InetSocketAddress(hostname, port);
socket = new Socket();
socket.connect(address, 2000); // 2000ms time out
// You can use the writer to write messages back out to the server
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
Now, regards to server-side you can do something as follows:
Write a program to allow clients to contact, given that they know your address.
Accept the connections, and store the sockets in a list.
When you need to send out a message, traverse the list and send the data to everyone on it.
You can start listening on your server with
this.socket = new ServerSocket(port);
You could (or even should(?)) make it threaded so that you can accept clients while serving others. You can accept new clients with:
socket.accept(); // Blocks, waiting for someone to connect, returns open socket
Feel free to pass that to a whole new class which can deal with BufferedWriter (and maybe even BufferedReader if you want to read from clients as well). That class is where you would implement things such as writeToClient(message)
Consider the situation where you have a ClientConnection class that has writeToClient(String s) method and (Server server, Socket socket) and initialized ArrayList conList.
Here is how you would follow:
In a separate thread in Server, accept connections with
ClientConnection con = new ClientConnection(this, socket.accept());
conList.add(con);
Then, when you want to write to clients:
for (ClientConnection c : conList) {
c.writeToClient("I'm sending you a message!");
}
I hope you get a vague idea of what you need to do. Read the Socket documentation, it's very useful. Also, as always with threaded applications, make sure you aren't doing things such as modifying a list while traversing it and avoid race conditions.
Good luck!

reusing socket streams

I have a server socket that I setup, and a client socket that connects to the server socket.
In the following sequence:
I open an ObjectOutputStream from the client to the server
On the server I open an ObjectInputStream from the accepted socket connection from the client
On the Server I open an ObjectOutputStream using the accepted socket connection from the client
On the client I open an ObjectInputStream
Everything works without error.
In a loop on the server I have the following
while(true) {
Map<Integer,Game> games = GameEngine.getGames();
System.out.println("Games is: " + games + " size is " + games.size());
secondaryOutputStream.writeObject(games);
secondaryOutputStream.flush();
// sleep for 2 seconds then send the games again
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
the secondaryOutputStream is the ObjectOutputStream from the server to the client.
What I am doing here is writing a map to the client. I do this repeatedly in a loop as you can see, using the same ObjectOutputStream.
There are no exceptions, so all the connections are sound. However, on the client side, I only receive the map once, after the socket connection is established with the server. If the map is updated and written to the client, I still see the original map values, when the server first wrote the map to the client. Can you reuse Object streams in this manner? Thanks indeed
ObjectOutputStream has a space saving (and identity preserving) feature where it keeps track of objects previously sent (based on object identity), and does not resend them. instead, it just sends a marker which indicates which object it previously sent, and the ObjectInputStream (which keeps a handle to all objects sent) just re-returns that object on the other end. you need to use ObjectOutputStream.reset() between each send so that the object will be completely resent. you can also use ObjectOutputStream.writeUnshared(), but this may not function exactly how you need.

to read the packet of bytes on client(client Socket) from server(ServerSocket) using java

i m a new .
i m a java developer(fresher) and currently i m working on BSE project and i m facing problem to read the packet of bytes on the client(client socket) from the server(server socket). if u can help me then please help me.
Thanks in advance
Well, if you want to interact directly with packets, then you need to use a DatagramSocket instead of the regular Socket and ServerSocket.
Then, you should visit this link to see a good tutorial on how to get started with sending and receiving individual packets.
The basic idea is that the Client or Server will block on the recieve() call while it waits for its partner to send a packet using send().
If you aren't interested in the individual packets like you indicated in your question, then you will want to use Socket and ServerSocket. The first step to communicating between the two involves code that will look similar to the following:
//Server
// this call will block until the client tries to connect to the server
Socket cientConn = new ServerSocket(8878).accept();
// now you can use the connection's input and output streams to send data
/******************/
// Client
Socket serverConn = new Socket(addressOfServer, 8878);
// now you can use the connections input and output streams
After you get connections set up, you will have basically 2 read/write loops. One on the client, and one on the server.
while(true) [
// check for data from an input stream
...
// respond with message back
}
You will need a similar loop for the client and the server.

Java Socket Connections in Queue

I have a client/server set up. The server (Provider.java) will accept 2 Socket connections. Each client, after they connect, are asked what type of game they would like to play - Tic Tac Toe, Chess, or Connect 5. Depending on their answer, the Socket connections are then stored in the particular game Queue. So, Tic Tac Toe has a Queue, and Connect 5 has a Queue, etc.
The Queues are implemented as follows:
Queue<Socket> qTTT = new LinkedList<Socket>();
Queue<Socket> qC5 = new LinkedList<Socket>();
Queue<Socket> qChess = new LinkedList<Socket>();
Each time a connection is added, the queues are checked to see if there are two connections. If there are two connections in a particular queue, then a game of that type will be launched, with the two connections. (designed with Factory design pattern).
if (qTTT.size() == 2) {
ObjectOutputStream out = null, out2 = null; // Client 1, Client 2
ObjectInputStream in = null, in2 = null; // Client 1, Client 2
Socket connection1 = null, connection2 = null;
connection1 = qTTT.remove();
connection2 = qTTT.remove();
try {
out = new ObjectOutputStream(connection1.getOutputStream());
out2 = new ObjectOutputStream(connection2.getOutputStream());
in = new ObjectInputStream(connection1.getInputStream());
in2 = new ObjectInputStream(connection2.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
SimpleGameFactory factory = new SimpleGameFactory();
GameStore store = new GameStore(factory);
Game game = store.orderGame("TTT");
System.out.println("We ordered a " + game.getName() + "\n");
tgame.setObject(game);
tgame.setSockets(connection1, connection2);
tgame.setStreams(in, out, in2, out2);
// Start the threaded game
tgame.start();
}
The above is throwing some sort of Stream corruption error. Here are my questions:
First, when the clients first connect, the socket connections are associated with an ObjectInputStream and an ObjectOutputStream. Those streams are not passed into the queue with the connections, so in the code above, new streams are assigned to the connections. Then, those streams are passed into the threaded game to start the game. Am I allowed to do this (assign new streams to the connections)? After streams had already been assigned to them?
Second, am I storing/removing the socket connections in the queue properly?
Thanks for your help!
UPDATE:
Here is the error I have been getting:
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2232)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2698)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:750)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:268)
at Pools.check_pools(Pools.java:34)
at Provider.start(Provider.java:85)
at StartServer.main(StartServer.java:16)
Turns out that I cannot assign an additional set of Input/Output streams to socket connections which have already been assigned a set of streams.
Thanks all for your help!
Honestly, that question looks like a solution to a college assignment.
Hint: write simple publisher/subscriber first. Set up one process that will be writing hello world to a socket and the second process that will be reading out of this socket. Then take it from there. I bet you're missing something obvious :-)
Are you sure that all of the opening handshake was retrieved from the socket before constructing the Object IO streams?
For example, if the client sends TTT\n\n as the game request and your code only reads the TTT\n and leaves the other \n on the stream, then the ObjectInputStream will fail.
You don't show the part where the user's game choice is read from the socket. So, this is just a guess.
My guess is that the exception has something to do with the code that you described at the beginning of your post. I'd start by looking into what you're doing with the sockets before your program gets to that snippet of code you posted.

Categories