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.
Related
I was making a simple client which connected to another server via Java Sockets and would await messages from that server and modify a video game it is running.
Socket socket = new Socket(server, 6667);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream( )));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream( )));
String line = null;
while ((line = reader.readLine( )) != null) {
System.out.println(line);
}
Currently the while loop occupies the entire main thread and a way to fix that would be to put this process on a separate thread. Best case scenario I would like to create a listener that gets pinged whenever the thread receives a new message and sends it off to interact with the main thread.
I was wondering whether there exists a built in layer for this kind of process in java sockets (like pubsub or onMessage) because it feels like a very popular use case. Please let me know if I've missed something like this in my search, I apologize for my ignorance and thank you in advance.
Edit:
TLDR:
I have a main thread which is being occupied by a game and I would like to read incoming messages from a server, is there any built in way to do it besides employing listeners the manual way?
I have a server-client setup over TCP where the client is sending a number of data sets to the server. The reading/writing uses ObjectInput/OutputStream. I don't have any problems under normal conditions, but when the data flow gets heavy, I get a StreamCorruptedException: invalid type code. The invalid code is different every time. I open the socket once and call a synchronized method to send data from multiple threads.
Client:
socket = new Socket("localhost", sockNum);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
public synchronized void sendMsg(Message msg){
try{
out.writeObject(security.signObject(msg, privKey));
out.reset();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Server:
ServerSocket server = new ServerSocket(sockNum);
Socket client = server.accept();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
while(threadActive){
Object line = in.readObject();
handleObject(line);
}
Update: I added out.reset() after each send, but that didn't help the problem. I've also added sleep statments in my loop to decrease the data rate. This gets rid of the error but is not a real solution.
Edit: So it's been a little while since I originally asked this, but I'm running into the problem again. I tried setting up my system so that after every sent message, the thread waits for an "acknowledge" message in return. If the receiving process has the StreamCorruptedException, it sends back a "resend" rather than an ack. This seems to be causing more problems than solutions. Any other ideas?
It sounds like you are writing to the output stream in a multi threaded way i.e. you are writing to it somewhere other than in your example.
BTW: Are you reset()ing the stream regularly to prevent a memory leak?
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!
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();
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.