Java TCP Socket programming throwing IO exceptions - java

I have written a client-server TCP Socket program such that the client will enter a string and that will be displayed by the server(echo program)... the condition is when I enter bye the program should exit... Well and good the client program is exiting ... but the server program is exiting with a java.io.DataInputStream.readUTF() and readFully exceptions.. plz help me.. whats wrong in the code...
/*Client*/
import java.net.*;
import java.io.*;
public class echoclient {
public static void main(String args[]) throws Exception
{
Socket soc = new Socket("127.0.0.1",4000);
OutputStream sout = soc.getOutputStream();
DataOutputStream out = new DataOutputStream(sout);
DataInputStream din = new DataInputStream(System.in);
while(true)
{
String message = din.readLine();
if(message.equals("bye"))
break;
out.writeUTF(message);
}
soc.close();
}
}
/*Server*/
import java.io.*;
import java.net.*;
public class echoserver {
public static void main(String args[]) throws Exception
{
ServerSocket server = new ServerSocket(4000);
Socket soc = server.accept();
System.out.println("Server Started....");
InputStream sin = soc.getInputStream();
DataInputStream in = new DataInputStream(sin);
while(true)
{
String fromClient = in.readUTF();
if(fromClient.equals("bye"))
{break;}
System.out.println("Client says : "+fromClient);
}
soc.close();server.close();
}
}
Exception:
Exception in thread "main" java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:340)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
at echoserver.main(echoserver.java:15)

I think that the answer is that that's just what happens. The EOFException is the only way that the DataInputStream tell the caller that it has reached EOF. So if your server attempts to read when the socket has been closed by your client, that's what will happen.
There are two solutions:
Catch and handle the EOFException.
Modify your "protocol" so that the client (somehow) tells the server when it has sent the last message ... and is going to close the socket.
Closing the DataOutputStream on the client side is a good idea, but it probably won't solve the problem. A DataOutputStream is not buffered and neither is a Socket's OutputStream, so there should be no data to be flushed. (Any data outstanding data in the network protocol stack should be transmitted when the Socket or OutputStream is closed.)

Related

Java SocketServer is accepting input from a Socket client but the Socket client is not receiving input from the SocketServer

I'm trying to learn Java Network Programming but I'm running into some roadblocks. I've written a server and a client already but every time I try to connect them, I instantly get a connection closed error. Then, I tried to edit it but now I get a connection refused error. Giving up on that, I decided to work on a very simple server to test out the basics of Sockets and ServerSockets. Doing so, I've come up with these two classes:
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;
public class SimpleServer {
public static void main(String[] args) throws Exception {
System.out.println("hey there");
ServerSocket server = new ServerSocket(50010);
Socket socket = server.accept();
System.out.println("Connection at " + socket);
InputStream in = socket.getInputStream();
int c = 0;
while ((c = in.read()) != -1) {
System.out.print((char)c);
}
OutputStream out = socket.getOutputStream();
for (byte b : (new String("Thanks for connecting!")).getBytes()) {
out.write(b);
out.flush();
}
in.close();
out.close();
socket.close();
server.close();
}
}
and
import java.net.Socket;
import java.io.*;
public class SimpleClient {
public static void main(String[] args) throws Exception {
System.out.println("Attempting connection");
Socket s = new Socket("130.49.89.208", 50010);
System.out.println("Cool");
OutputStream out = s.getOutputStream();
for (byte b : (new String("Hey server\r\nThis message is from the client\r\nEnd of message\r\n")).getBytes()) {
out.write(b);
out.flush();
}
InputStream in = s.getInputStream();
int c = 0;
System.out.println("this message will print");
while ((c = in.read()) != -1) {
System.out.print((char)c);
System.out.println("this does not print");
}
out.close();
in.close();
s.close();
}
}
The server receives the client's message perfectly fine, but then when it is the server's turn to write to the client, everything just blocks.
Server's output:
-java SimpleServer
----hey there
----Connection at Socket[addr=/130.49.89.208,port=59136,localport=50010]
----Hey server
----This message is from the client
----End of message
Client's Output:
-java SimpleClient
----Attempting connection
----Cool
----this message will print
The client and the server both run on my laptop on an ethernet connection to a university's internet connection, if that helps.
According to the Javadocs, the InputStream.read() is described as:
If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
In your case, the only possibility to break the while-loop is when the client closes the connection, thereby resulting in end-of-stream.
This is expected as per what you've coded!
Your server code is getting stuck here and thus never writing back to the client
while ((c = in.read()) != -1) {
System.out.print((char)c);
}

Making simple client/proxy/server programs using sockets in java

I'm working on an assignment where I have to make 3 programs, a client, a proxy, and a server. The client is supposed to send messages to the server by sending them to the proxy, which sends them to the server, and vice versa. The server waits for the proxy to connect to it, and the proxy waits for the client to connect to it, then the client sends a message to the proxy which gets sent to the server. When I compile them though, while the proxy gets the message fine, the serve gets an error.
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at Server.run(Server.java:18)
at Server.main(Server.java:8)
Here is the client code
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws Exception{
Client serv = new Client();
serv.run();
}
public void run() throws Exception{
Socket sock = new Socket("localhost", 7777);
PrintStream ps = new PrintStream(sock.getOutputStream());
ps.println("Hello Server");
sock.close();
}
}
Here is the proxy,
import java.net.*;
import java.io.*;
public class Proxy {
public static void main (String[] args) throws Exception{
Proxy serv = new Proxy();
serv.run();
}
public void run() throws Exception{
ServerSocket ss = new ServerSocket(7777);
Socket sock = ss.accept();
InputStreamReader ir = new InputStreamReader(sock.getInputStream());
BufferedReader br = new BufferedReader(ir);
String message = "";
message = br.readLine();
System.out.println(message);
Socket sck = new Socket("localhost", 8888);
PrintStream ps = new PrintStream(sock.getOutputStream());
boolean waiting = true;
while(waiting){
if(message != null){
ps.println("Hey Server, Client says: " + message);
waiting = false;
}
}
sock.close();
}
}
and here is the server
import java.net.*;
import java.io.*;
public class Server {
public static void main (String[] args) throws Exception{
Server serv = new Server();
serv.run();
}
public void run() throws Exception{
ServerSocket ss = new ServerSocket(8888);
Socket sock = ss.accept();
InputStreamReader ir = new InputStreamReader(sock.getInputStream());
BufferedReader br = new BufferedReader(ir);
System.out.println(br.readLine());
sock.close();
ss.close();
}
}
Does anybody know what I'm doing wrong?
Look at your proxy. First the sock Socket represents the connection with the client, then the sck Socket represents the connection with the server. However, when you create your PrintStream ps to connect with the server, you are using sock.getOutputStream as opposed to sck.getOutputStream. You are telling it to send information back to the client, which does not have an open BufferedReader to interpret, nor an open Socket at that point. Attempting to write to a closed connection results in a connection reset exception.
Secondly (though this is not causing the error), your proxy while loop is all jacked up. If you examine it, it will obviously cycle through at least once because waiting is defaulted to true. Then, you are checking to see if message != null. In this case, message will never be null because the client is set to always send the same message, and only one message. Most importantly, however, if for whatever reason message was null, there is nothing in the while loop to change that -- it does not attempt to read the next value from br or anything, so you will simply be stuck in an infinite while loop.
I believe what you were looking for was this:
String message;
while((message = br.readLine()) != null){
ps.println("Hey server, Client says: " + message);
}
But as I said, a while loop is not necessary in this case because the client is set to send only one message anyways, so you can simply do this:
ps.println("Hey server, Client says: " + message);
... without any sort of looping.

java.io.StreamCorruptedException: invalid stream header: 54657374

I am trying to read a string which is send from client using Socket program, The code as follows:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ClassNotFoundException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServerExample {
//static ServerSocket variable
private static ServerSocket server;
//socket server port on which it will listen
private static int port = 5000;
public static void main(String args[]) throws IOException, ClassNotFoundException{
//create the socket server object
server = new ServerSocket(port);
//keep listens indefinitely until receives 'exit' call or program terminates
while(true){
System.out.println("Waiting for client request");
//creating socket and waiting for client connection
Socket socket = server.accept();
//read from socket to ObjectInputStream object
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//convert ObjectInputStream object to String
String message = (String) ois.readObject();
System.out.println("Message Received: " + message);
//create ObjectOutputStream object
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//write object to Socket
oos.writeObject("Hi Client "+message);
//close resources
ois.close();
oos.close();
socket.close();
//terminate the server if client sends exit request
if(message.equalsIgnoreCase("exit")) break;
}
System.out.println("Shutting down Socket server!!");
//close the ServerSocket object
server.close();
}
}
But I am getting error as follows while reading the string from client:
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 54657374
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:803)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:298)
at SocketServerExample.main(SocketServerExample.java:29)
I searched and not managed find the bug. Please help me.
Clearly you aren't sending the data with ObjectOutputStream: you are just writing the bytes.
If you read with readObject() you must write with writeObject().
If you read with readUTF() you must write with writeUTF().
If you read with readXXX() you must write with writeXXX(), for most values of XXX.
You can't expect ObjectInputStream to automagically convert text into objects. The hexadecimal 54657374 is "Test" as text. You must be sending it directly as bytes.

How to correctly close a socket and then reopen it?

I'm developing a game for a class that I am in, and it is about 99% done. However, I realized there is a problem: If the server and client disconnect, and the client attempts to reconnect (and the server is back up and running fine), the client is not making a new connection.
The server and client are both multi-threaded. If I send the client a Kick message, what happens is the client will close its socket. If I reconnect, I get a SocketException: socket closed even though whenever connect is pressed, a new Client is constructed, which is basically just a class that creates a socket and connects to the server with a get/send thread.
Do you think there is anything I am doing illogically? It is like it is attempting to use the old Socket and Client that were constructed, but if I do some println calls, I can see that it does construct a new one and they are in different memory locations.
Thanks!
After closing a socket, you cannot reuse it to share other data between Server and Client classes. From the Java Socket API, about close() method's description:
Any thread currently blocked in an I/O operation upon this socket will
throw a SocketException.
Once a socket has been closed, it is not available for further
networking use (i.e. can't be reconnected or rebound). A new socket
needs to be created.
Closing this socket will also close the socket's InputStream and
OutputStream.
If this socket has an associated channel then the channel is closed
as well.
Then, it isn't possible to close a socket and reopen it. That's the reason, I think, of the exception being thrown.
It can be easy! I made this program (server side):
import java.net.ServerSocket;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class Host{
public static void main(String[] args) throws Exception{
while(true){
ServerSocket ss = new ServerSocket(1300);
Socket s = ss.accept();
DataInputStream din = new DataInputStream(s.getInputStream());
String msgin = din.readUTF();
System.out.println(msgin);
ss.close();
s.close();
din.close();
}
}
}
Client side:
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
public class Client{
public static void main(String[] args) throws Exception{
while(true){
Socket s = new Socket("localhost", 1300);
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
dout.writeUTF("hello");
s.close();
dout.close();
}
}
}
It works, beacuse you can declare tons of Sockets with the same ServerSocket, so for example this works too:
ServerSocket ss = new ServerSocket(1300);
Socket a = ss.accept();
Socket b = ss.accept();
Socket c = ss.accept();
and you have 3 Sockets...
Remember: java waits for a client to connect when you declare a Socket!
Code:
Client:
import java.net.Socket;
public class client {
public static void main(String[] args) throws Exception{
Socket a = new Socket("localhost", 1300);
Thread.sleep(3000);
Socket b = new Socket("localhost", 1300);
Thread.sleep(3000);
Socket c = new Socket("localhost", 1300);
Thread.sleep(3000);
a.close();
b.close();
c.close();
}
}
Server:
import java.net.ServerSocket;
import java.net.Socket;
public class server {
public static void main(String[] args) throws Exception{
ServerSocket ss = new ServerSocket(1300);
System.err.println("Listening...");
Socket a = ss.accept();
System.err.println("1");
Socket b = ss.accept();
System.err.println("2");
Socket c = ss.accept();
System.err.println("3");
}
}

why doesn't my client read correctly the outputStream sent by the Server?

It's a simple client-server where Server using a BufferedWriter object would send to the Client receiving in the object BufferedReader.
When I use OutputStream and PrintWriter for the Server and InputStream and Scanner for the Client it works well.
What happens is that the client in Buffered way reads -1 if I'm sending an int and null for String.
I hope my English makes sense. ;P
That's the code:
Server:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8189);
Socket incoming;
incoming = server.accept();
try {
// OutputStream output = incoming.getOutputStream();
// PrintWriter outStream = new PrintWriter(output, true /*autoFlush*/);
// outStream.println("ENTER");
BufferedWriter output = new BufferedWriter(new
OutputStreamWriter(incoming.getOutputStream()));
output.write(3);
System.out.println("\nSent");
} finally {
incoming.close();
}
}
}
Client:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
//Client theClient= new Client();
Socket RTSPSocket;
int ServerPort = 8189;
//server name address
String ServerHost = "localhost";
//get Server IP Address
InetAddress ServerIPAddress = InetAddress.getByName(ServerHost);
RTSPSocket = new Socket(ServerIPAddress, ServerPort);
try {
/*
InputStream input = theClient.RTSPSocket.getInputStream();
Scanner in = new Scanner(input);
String line = in.nextLine();
System.out.println(line);
*/
BufferedReader input = new BufferedReader(new
InputStreamReader(RTSPSocket.getInputStream()));
//String line = input.readLine();
//System.out.println("\nRicevuto: " + line);
System.out.println(input.read());
} catch (Exception e) {
System.err.println("Error: " + e);
}
}
}
try putting the following code after output.write(3);
output.flush();
The BufferedOutputStream is built to only send the data when the buffer is full (I believe the default 1024 bytes). So, to force the data to be sent you need to flush the stream.
You have to flush data to receive them in the client part.
output.write(3);
output.flush();
System.out.println("\nSent");
When you have an OutputStream (or a Writer) you have to flush your data, this way you're 100% sure that what you wanted to be send has been sent.
Most (if not all) the OutputStream subclasses use a "mini buffer" which is flushed only when it's full or you manually call flush(). In your case, it's even more flagrant because you're using a BufferedWriter.
Another thing, when you use streams/writers, you really should close them after you're finished, one of the main thing close() do (most of the time) is flushing the last data remaining in the "mini buffer".
Resources :
Javadoc - OutputStream.flush()

Categories