I'm trying to make a very basic example of a network connection where I use an ObjectOutputStream, ObjectInputStream and sockets. The client sends the string "Hello" to the server. As you see this string is sent 10 times with the very same ObjectOutputStream. Then the server sends the string "Goodbye" to the client. The console should display 10 times the string "hello" and 10 times the string "Goodbye". But they are shown only one time. I read in many threads about the method reset() of the ObjectOutputStream. But it does not seem to work for me. Any ideas what the problem is? I've already tried many different things without success.
Here is the client:
try
{
Socket socket = new Socket("localhost", 5555);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
int i = 10;
while (i > 0)
{
//send String
out.writeObject("Hello");
out.flush();
out.reset();
//receive String
String result = (String) in.readObject();
System.out.println(result);
i--;
}
} catch (IOException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} finally
{
out.close();
in.close();
socket.close();
}
Here is the server:
try
{
ServerSocket server = new ServerSocket(5555);
while(true)
{
try
{
Socket client = server.accept();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
//receive String
String input = (String) in.readObject();
System.out.println(input);
out.writeObject("Goodbye");
out.flush();
out.reset();
} catch(IOException e1)
{
e1.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
} catch(IOException e2)
{
e2.printStackTrace();
}
Your server is only reading and writing once to each accepted socket. So the client can't possibly read an object ten times.
Your server also isn't closing the stream when it's finished.
Related
I wrote a Java socket server which will keep connection alive until client disconnected. And my client code will keep pushing message to this server app.
But when I run those programs a while, I also seem an unusual condition that Server will hangs while reading input stream from client within unpredictable period. It always hang at inData.read(b) because I see it printed "receiving..." on log when this problem occurred"; even I killed my client, server app still hangs right there.
But when I press Ctrl+C at the console which runs server app after this problem occurred, it will continue to work. This is really annoying.
Is there anyway to solve this Unusual problem nicely?
Server Code:
static ServerSocket server;
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Socket socket = null;
String inIp = null;
BufferedInputStream inData;
BufferedOutputStream outData;
while (true) {
try {
synchronized (server) {
socket = server.accept();
}
inIp = String.valueOf(socket.getInetAddress());
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Incoming connection " + inIp);
}
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
String reply = "Hey";
byte[] b = new byte[10240];
String data = "";
int length;
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("InetAddr = " + inIp + ", receiving...");
}
// read input stream
length = inData.read(b);
data += new String(b, 0, length);
if (Log4j.log.isEnabledFor(Level.INFO)) {
Log4j.log.info("Data Length: " + length + ", Received data: " + data);
}
// output result
outData.write(reply.getBytes());
outData.flush();
}
} catch (Exception e) {
String tempStr = e.toString();
Log4j.log.error("Service error during executing: " + tempStr);
}
}
Client Code:
Socket client = new Socket();
InetSocketAddress isa = new InetSocketAddress("127.0.0.1", "1234");
String data = "Hi";
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
// send msg
out.write(data.getBytes());
out.flush();
System.out.println("Message sent, receiving return message...");
// get return msg
int length;
byte[] b = new byte[10240];
// read input stream
length = in.read(b);
retMsg = new String(b, 0, length);
System.out.println("Return Msg: " + retMsg);
Thread.sleep(60000);
} catch (java.io.IOException | InterruptedException e) {
System.out.println("Socket Error!");
System.out.println("IOException :" + e.toString());
}
}
try {
server = new ServerSocket("1234");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Don't write code like this. The catch block should be at the end, and all the code that depends on the success of new ServerSocket should be inside the try block.
synchronized (server) {
socket = server.accept();
}
Synchronization is not necessary here.
while (true) {
inData = new BufferedInputStream(socket.getInputStream());
outData = new BufferedOutputStream(socket.getOutputStream());
A large part of the problem, if not all of it, is here. You keep creating new buffered streams, every time around this loop, which means that anything the previous streams have buffered is thrown away. So you are losing input. You should create both these streams before the loop.
while(true) {
try {
if(!client.isConnected())
client.connect(isa, 30000);
This is pointless. Remove. You haven't shown how the client socket was created, but if you created it unconnected you should have connected it before entering this loop.
BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream in = new BufferedInputStream(client.getInputStream());
Here again you must create these streams ahead of the loop.
a few days ago, I started to code a little multiplayer game, in wich I use ObjectInputStreams and ObjectOutputStreams in order to exchange data with a server. But for some reason, the server does not recieve anything. So I searched for some help, but everything I found was, that I have to flush the ObjectOutputStream. Of course I did this, but it is not the solution for my problem. So I wrote a tiny test application, that does the same as my game. But there is still the same problem: The InputStream does not recieve anything. So here's my code for the test app:
Server application:
try {
ServerSocket srvr = new ServerSocket(12975);
Socket client = srvr.accept();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.flush();
System.out.println("server ready!");
String line = "";
while(!line.equalsIgnoreCase("exit")){
while(in.available() <= 0){}
line = in.readObject().toString();
System.out.println(">>> recieved: " + line);
}
client.close();
srvr.close();
System.exit(0);
} catch (IOException e) {
System.err.println("ERROR: " + e.getMessage());
e.printStackTrace();
System.exit(1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
And here's the client application:
try {
Socket client = new Socket("localhost", 12975);
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.flush();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
System.out.println("client ready!");
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while(!line.equalsIgnoreCase("exit")){
System.out.print("> ");
line = input.readLine();
out.writeObject(line);
out.flush();
}
client.close();
System.exit(0);
} catch (IOException e) {
System.err.println("ERROR: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
I tried to do this to both sides: Server->Client and Client->Server, but both Sockets did not recieve anything. Any research failed, because everyone seems to forget the flush() after constructing the OutputStream, but then it works.
So I hope, anyone knows this problem and is able to help me.
P.S: I am not from England nor from America, so sorry, if my English contains mistakes! :D
Just try this , this is working.
while(!line.equalsIgnoreCase("exit")){
while(in.available() <= 0){
line = in.readObject().toString();
System.out.println(">>> recieved: " + line);
}
}
You have mistaken with your second while loop parenthesis in server code.
I am doing a client to server Log-in communication.
I met a java.net.SocketException: broke Pipe at Server end. And I have narrowed the
problem to one single line at the client end. If I move a position for this line,
the code works. plese see the following code.
Client End:
Socket socket = new Socket(Const.destIp, 12101);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(this.message);
out.close();//Line that cause problem
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ServerToClientLogin msg = (ServerToClientLogin) in.readObject();
//out.close();//move it to here, problem solved
in.close();
socket.close();
Server end:
while (true) {
socket = _serverSocket.accept();
in = new ObjectInputStream(socket.getInputStream());
msg = (ClientToServerLogin) in.readObject();
ServerToClientLogin msgToSend = null;
out = new ObjectOutputStream(socket.getOutputStream());
msgToSend = handleLoginRequest(msg);
if(msgToSend != null) out.writeObject(msgToSend);
try { in.close(); } catch (IOException e) {e.printStackTrace();}
try { out.close();} catch (IOException e) {e.printStackTrace(); }
try { socket.close();} catch (IOException e) {e.printStackTrace();}
}
Since readObject and writeObject are blocking call, I have no idea why close it earlier would case such problem.
out.close();: Closes this (out) output stream and releases any system resources associated with this stream.
See the API here.
what im trying to do:
client connects to server
server sends READY
client takes screenshot and sends it
server processes image
server sends READY
client takes screenshot and sends it
server processes image
...
i have a working client and server:
Client() {
try {
socket = new Socket(host, 4444);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
int ix = 0;
while (true) {
switch (in.readInt()) {
case Var.READY:
image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ByteArrayOutputStream byteArrayO = new ByteArrayOutputStream();
ImageIO.write(image,"PNG",byteArrayO);
byte [] byteArray = byteArrayO.toByteArray();
out.writeInt(byteArray.length);
out.write(byteArray);
System.out.println("send screen " + ix++);
break;
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection " + e.getMessage());
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
Server:
public class ServerWorker implements Runnable {
private Socket socket = null;
DataInputStream in = null;
DataOutputStream out = null;
ServerWorker() {
}
synchronized void setSocket(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
notify();
}
public synchronized void run() {
int ix = 0;
try {
while (true) {
out.writeInt(Var.READY);
int nbrToRead = in.readInt();
byte[] byteArray = new byte[nbrToRead];
int nbrRd = 0;
int nbrLeftToRead = nbrToRead;
while(nbrLeftToRead > 0){
int rd =in.read(byteArray, nbrRd, nbrLeftToRead);
if(rd < 0)
break;
nbrRd += rd; // accumulate bytes read
nbrLeftToRead -= rd;
}
//Converting the image
ByteArrayInputStream byteArrayI = new ByteArrayInputStream(byteArray);
BufferedImage image = ImageIO.read(byteArrayI);
System.out.println("received screen " + ix++);
//image.flush();
File of = new File("RecvdImg" + ix + ".jpg");
ImageIO.write(image, "PNG" ,of);
System.out.println("Sleeping 1..");
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
So whats the question you might ask?
Well, am i doing it right?
Activity monitor tells me the client side takes about 40% of cpu constantly, that cant be good.
Just wondering if anyone could point me in the right direction to making the code more efficient.
Client could detect if the image has changed, and if it hasn't it could send to the server a flag indicating to reuse the previous image received. Or you can "diff" the image and send only the changed areas to the server, which will recompose the image. That reduces bandwidth usage and perhaps also CPU usage.
Also, the client should sleep a while in the receiving endless loop, after the switch.
In my opinion you should avoid using infinit-loops like
while (true)
Loops like
while(!connectionAborted)
are better in such situations.
Also you should take a look at
Socket.setSoTimeout()
SoTimeout cancels the reading-process of i.e. in.readInt() after an specific amount of time, depending on your parameter.
The result is that at this line a SocketTimeoutException is thrown, but your code is not stuck at this codeline and can react on i.e. different user inputs.
Client code:
try {
Socket socket = new Socket(ip, port);
OutputStream output = socket.getOutputStream();
ObjectOutputStream out = new ObjectOutputStream(output);
InputStream input = socket.getInputStream();
ObjectInputStream in = new ObjectInputStream(input);
out.writeByte(1);
FileHandler fh = (FileHandler) in.readObject();
//processing stuff
out.flush();
out.close();
output.flush();
output.close();
input.close();
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
Server code:
try {
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
InputStream input = socket.getInputStream();
ObjectInputStream in = new ObjectInputStream(input);
int type = in.readByte();
//processing stuff (which includes closing the streams and sending FileHandler object)
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
The server never receives the byte. It just waits for the byte from the client, and it never comes. I'm not sure why it isn't sending, or getting received. Any help is much appreciated.
If I had to make a guess it's because in your client you block on in.readObject(); waiting for the server to send you something thus never flush the output stream thus ... nothing ever gets sent.
Move your read to after you flush your output stream.
Try to use the writeObject and readObject methods. Also write an Integer not an int to the stream. Read this really good lecture before proceeding any further.
This is also a good lecture for your problem.
Regards!