Facing exception on closing client in Java - java

I am new to socket programming in java so facing a problem seems not difficult but unable to solve due to unfamiliarity. Following are codes for Client and Server.
Server Code:
public class connectionServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
String clientSentence;
String capitalizedSentence;
BufferedReader inFromClient;
DataOutputStream outToClient;
BufferedReader inFromUser;
try {
ServerSocket welcomeSocket = new ServerSocket(70);
Socket connectionSocket;
connectionSocket = welcomeSocket.accept();
System.out.println("Connection accepted for " + connectionSocket.getInetAddress() + ": " + connectionSocket.getPort());
InputStreamReader input = new InputStreamReader(connectionSocket.getInputStream());
inFromClient = new BufferedReader(input);
while (true)
{
if(input.ready())
{
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
}
String tempString = "FROM SERVER: What's problem......";
try
{
Thread.currentThread().sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
outToClient = new DataOutputStream(connectionSocket.getOutputStream());
if(outToClient != null)
{
outToClient.writeBytes(tempString + "\n");
outToClient.flush();
}
}
}
catch (IOException e)
{
System.out.println(e);
e.printStackTrace();
}
}
}
Client Code:
public class connectionClient {
static Socket clientSocket = null;
//////////////////////////////////////////
//////////////////////////////////////////
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
String sentence;
String modifiedSentence;
attachShutDownHook();
try
{
clientSocket = new Socket("127.0.0.1", 70);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());;
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes("FROM CLIENT 2: Hello \n\n");
while(clientSocket.isConnected())
{
sentence = "Please reply me....";
try
{
Thread.currentThread().sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
if(inFromServer.ready())
{
modifiedSentence = inFromServer.readLine();
System.out.println(modifiedSentence);
}
outToServer.writeBytes("FROM CLIENT 2:" + sentence + "\n");
outToServer.flush();
}
}
catch(IOException e)
{
System.out.println(e);
}
finally
{
System.exit (0) ;
}
}
}
When I stop the client following exception is thrown on server side
java.net.SocketException: Connection reset by peer: socket write error
java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:132)
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:276)
at connectionserver.connectionServer.main(connectionServer.java:57)
Any help in this regard will be highly appreciated. Thanks

This usually means you have written to an connection that had already been closed by the peer. In other words, an application protocol error.
Your code needs work.
Don't use ready(): just block in read() until data arrives. At present you're smoking the CPU while ready() returns false. This is probably causing the error.
isConnected() is always true after you connect the socket. It won't magically return false when the peer closes his end. You have to detected that via EOS or an exception. Looping on while (isConnnected()) isn't valid.
Don't mix streams and readers and writers. You're using a BufferedInputStream: use a BufferedWriter at the other end.

Related

Turning single threaded server into concurrent/multithreaded

I've created a single threaded server but turn around times are slow when processing multiple requests, how would i implement multithreading into this? I've attempted a few ways but it tehy alwasy have issues such as only being able to accept a single client or only taking commands from the first client that joined the server.
`
import java.net.*;
import java.io.*;
public class SocketServer {
public static void main(String[] args) {
if (args.length < 1)
return; // minimum length
int port = Integer.parseInt(args[0]); // set port
SocketServer.start(port);
}
public static void start(int port) {
// initialize server sockets and accept connection
try (ServerSocket serverSocket = new ServerSocket(port);) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
// read data from client
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); // buffered reader for strings
// send data to client
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true); // sends data in text format, the true in autoflush
// clears data after each call
String text;
//
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
// close
System.out.println("Connection Terminated.");
socket.close(); // closes connection with client
serverSocket.close();
}
} catch (IOException ex) // catch server exception and prints it
{
System.out.println("Encountered an exception, connection terminated.");
} catch (NullPointerException e) {
System.out.println("Encountered an exception, connection terminated.");
}
}
}
`

Server-Client what is wrong here?

So this is the first Server-Client I am trying to 'setup' but it does not work as I want it to. Here is What I want:
The Client to do: (see comments in the code for the Client)
A 'user input' should be read by the Client
Send the 'user input' to the server
receive back something from the server
The server to do: (See the comments in the code for Server)
receive the 'user input' that read by the client
Do something with the 'user input'
Send what was done in (2), back to the client.
It is not working the only right thing it is doing is that it receives the input from the 'user', that is it:
public class Cli {
BufferedReader in;
PrintWriter out;
Socket s;
public Cli(int port){
try {
s = new Socket("127.0.0.1", port);
out = new PrintWriter(s.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader
(s.getInputStream()));
} catch (UnknownHostException e) {
System.out.print("fel");
} catch (IOException e) {
System.out.print("fel");
}
}
public void startaClient(){
BufferedReader stdIn = new BufferedReader (new InputStreamReader(System.in));
try {
while(true){
String userInput = stdIn.readLine();// get the user input (1)
System.out.print("from user: " + userInput);
out.write(userInput); // sends to server (2)
System.out.println(in.readLine()); // receive from server(3)
}
} catch (Exception e){
System.out.println("fel1");
}
}
public static void main(String[] args){
Cli c=new Cli(4002);
c.startaClient();
}
Here is the code for the Server:
public class Ser {
ServerSocket s;
public Ser()throws Exception{
s = new ServerSocket(4002);
}
public void startaServern()throws Exception {
while (true) {
Socket socket = s.accept(); //waits for new clients, acceptera inkommande förfrågan
Trad t = new Trad(socket);
t.start();
}
}
public static void main(String[] args)throws Exception{
Ser b = new Ser();
b.startaServern();
}
}
public class Trad extends Thread {
Socket socket;
BufferedReader in;
PrintWriter out;
public Trad(Socket s){
socket=s;
try{
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); //
out=new PrintWriter(socket.getOutputStream(),true);
}catch(Exception e){System.out.println("fel");}
}
public void run(){
while(true){
try{
String theInput = in.readLine(); //read, receive message from client (1)
String res = theInput+"blabla"; // do something with the message from the client (2)
out.write(res); // send it back to the client (3)
} catch(Exception e) {
System.out.println("fel1");
}
}
}
}
When you do readLine() it will read a line i.e. until it reaches a new line.
Unless you send a new line it will wait forever. I suggest you send a newline so the reader knows the line has ended.
Since you are using a PrintWriter the simplest solution is to use
out.println(res);
instead of out.write(res);

Read/write in simple client-server app in Java

I'm new with Java and I'm trying to learn threads and socket. So decide to make simple client-server application following official java tutorial. My idea is simple - server wait for connection, if appears, it makes new thread with new socket, input and output. Client side -> make connection; new thread with socket, input, output and stdIn (to read line and after that send it to the server). But something is wrong (don't have any idea why) with my code. The connection is established, there's no exceptions. Could someone explain why doesn't work and how to fix it? Also could you have any suggestions about the code (probably it's not with best practices and things like that):
Client side:
public class Client {
private BufferedReader reader;
private Socket sock;
private PrintWriter writer;
public static void main(String[] args) {
Client client = new Client();
client.go();
}
public void go() {
setUpNetworking();
}
private void setUpNetworking() {
try{
sock = new Socket("127.0.0.1", 5000);
System.out.println("Network established");
ServerThread serverThread= new ServerThread(sock);
serverThread.start();
System.out.println("Type your message: ");
} catch (IOException e) {
System.out.println("Problem with establishing the network: " + e);
}
}
class ServerThread extends Thread {
Socket socket;
PrintWriter out;
BufferedReader in;
BufferedReader stdIn;
ServerThread(Socket socket) {
this.socket = socket;
try{
out = new PrintWriter(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
stdIn = new BufferedReader(new InputStreamReader(System.in));
}catch (IOException e) {
System.out.println("Problem with trying to read/write to server: " + e);
}
}
#Override
public void run() {
String fromServer;
String fromClient;
while(true){
try{
if((fromServer = in.readLine()) != null) System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null) out.println(fromClient);
}catch(Exception e) {
System.out.println("msg exception: " + e);
}
}
}
}
}
Server side:
public class Server {
//Run server until keepGoing = false
private boolean keepGoing = true;
public static void main(String[] args) {
Server server = new Server();
server.go();
}
public void go() {
try {
ServerSocket serverSocket = new ServerSocket(5000);
while(keepGoing) {
Socket clientSocket = serverSocket.accept();
ClientThread t = new ClientThread(clientSocket);
t.start();
}
} catch (IOException e) {
System.out.println("Problem with socket/network: " + e);
}
}
class ClientThread extends Thread {
Socket clientSocket;
PrintWriter out;
BufferedReader in;
ClientThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try{
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
System.out.println("Problem with creating in/out: " + e);
}
}
#Override
public void run() {
String message;
while(keepGoing) {
try{
message = in.readLine();
out.println(message);
System.out.println(message);
} catch (IOException e){
System.out.println("Exception while try to read line: " + e);
}
}
}
}
}
PS I've changed a bit the code - instead of made ClientThread Class, I made new runnable class and pass that variable to thread class. Inspired by this question: "implements Runnable" vs. "extends Thread".
I think the problem is that both server and client are waiting for any input. Server:
message = in.readLine();
Client:
if((fromServer = in.readLine()) != null)
System.out.println(" " + fromServer);
else if((fromClient = stdIn.readLine()) != null)
out.println(fromClient);
But the client code already blocks on the fromServer = in.readLine() part, so it never gets to read from standard in, and thus nothing will be sent out to the server.
You could move your attempt to read from standard in to the setUpNetworking method, right after the System.out.println("Type your message: ");. Build a loop there which you exit if the user types "exit" or "quit" or something like that:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String read = "";
do {
read = stdIn.readLine();
System.out.println("Read from stdin: " + read);
serverThread.send(read);
}
while (!read.equals("exit"));
The ServerThread.send() method is simple:
void send(String string) {
System.out.println("Sending to server: " + string);
out.println(string);
}
However, to make it work, you either have to flush the stream manually after writing to out, or use the following constructor:
out = new PrintWriter(socket.getOutputStream(), true);
See the PrintWriter's JavaDoc: True means auto-flush on newline.
I tested this setup and it worked for me. I was able to send something from the client to the server.
However, this is only the first step. I would implement both reading and writing as separate threads, for both client and server. And there is no graceful shutdown of sockets implemenented yet. A more complete yet simple example can be found on Oracle.

Socket data does not appear to be getting through to client

I've written some serverside socket handling code and I'm concerned that potentially my packets are not always making it back to the client. I am logging all my events and in my log files it says I am sending the information. But the client is also logging events and in their logs they say they do not receive anything.
My code to send the data is as follows:
public void write(Packet packet) {
String data = packet.serialize();
log("Send=[" + data + "]", "Write"); // log to file
try {
_writer.write(data);
_writer.flush();
} catch (Exception ex) {
log(ex, "write");
}
}
Each socket is created on a new thread and I create my writers and readers immediately like so (in the public run method):
// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
.getOutputStream()));
_reader = new SocketReader(_socket);
SocketReader is just a wrapper class I created for listening for responses and has a public read method like so:
public String read() throws IOException, SocketTimeoutException {
_socket.setSoTimeout(_timeOut);
if(_reader == null)
_reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
// read from the stream
return new PacketDataInputStream(_reader).read();
}
The PacketDataInputStream wrapper class:
BufferedReader _reader = null;
public PacketDataInputStream(BufferedReader reader)
{
_reader = reader;
}
public String read() throws IOException, SocketException {
StringBuilder builder = new StringBuilder();
int c = 0;
while((c = _reader.read()) != -1)
{
char ch = (char)c;
builder.append(ch);
if(ch == PacketConstants.ETX)
break;
}
if(builder.length() > 0)
return builder.toString();
else
return null;
}
The way I'm creating the actual socket listener objects is pretty standard I think:
InetAddress address = InetAddress.getByName(IP);
server = new ServerSocket( port, 0, address);
// My own manager class to handle all the sockets connected
WebSocketManager manager = new WebSocketManager(this);
Socket connection = null;
while(bContinue)
{
connection = server.accept();
if(bContinue) {
// assign the socket to a new thread and start
// that thread
manager.newSocket(connection);
} else {
connection.close();
}
}
Is is possible that I'm using the wrong objects for sending the data back.
Should I even be using a bufferedwriter and reader? I had thought that these were the best way to go but now I'm not so sure.
It's important to note that this does not happen all the time, just sporadically. It could be the clients code having bugs but I need to make sure that I'm doing it correctly before going back to them.
This code is run on a Linux Ubuntu server. Logging occurs to a text file, nothing special there. My log files show the Send="" data going back to the client and no exception so it appears as if the .write and .flush() worked? Socket connections are persistant and only closed by the client and or network issues.
UPDATE ----- Client Side code -------:
I did manage to get some of the client side code for how they are handling the send and receiving of data (just in case it's more obvious on their end). The client is actually connecting to this server via an Android device (if that helps).
Creation of socket
static final int BUFFER_SIZE = 20000; // Maximum packet size
java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
Sending:
try {
// Send the packet:
OutputStream stream = socket.getOutputStream();
stream.write(p.getByteArray ());
stream.flush();
// Update the time:
lastPacketSendTime = new Date ();
} catch (IOException e) {
setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
return false;
}
Receiving:
socket.setSoTimeout(timeout);
// Get the reader:
inputStream = socket.getInputStream();
while (true) {
// Get the next character:
int value = inputStream.read();
// Check for -1, indicating that the socket is closed:
if (value == -1) {
// The socket is closed remotely, so close it locally as well:
disconnect();
inputStream = null;
return null;
}
// ... and a bunch of other stuff to handle the actual data
}
EDIT 14-Nov:
This is actually proving to be more of a problem now. Both the client logs and the server logs appear to be sending. But at times the data doesn't appear to come through or if it does it is sometimes coming through 10 - 30 - 60 second delayed.
I can provide more information if required.
When you use BufferedReaders and BufferedWriters things get buffered. How about using the input and output streams directly.. Also, writers are character based, I don't know if you need to send binary data but if so that will be a problem with writers.
I am not sure whether this will be to your any use or not.. but i am giving you the code i used for client server communication..
Client Side:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Code:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}

Java networking using threads, when one client leaves the other cannot communicate to the server

I'm trying to create a server in java which accepts clients. Currently, two clients can connect to the server. However, when one leaves the other client can no longer communicate with the server. I think the issue is that my clientSocket is created outside my thread, which means it must be declared as 'final' because I use an innerclass. However, if I move it into the thread it cannot create the clientSocket. Any ideas on how to fix this? Thanks in advance.
Comment: If I close the clientSocket when the client leaves it says "Broken Pipe" error because the clientSocket is final so it cannot be changed - ie the clientSocket is the same for both clients.
private BufferedWriter writer;
private LODGame game;
public Server(int port) throws Exception {
try{
// Listen on the given port.
serverSocket = new ServerSocket(port);
game = new LODGame();
}
catch(BindException e){
throw new Exception("Failed to create a server socket: "+
e.getMessage());
}
}
public Server(int port, String map) throws Exception {
try{
// Listen on the given port.
serverSocket = new ServerSocket(port);
game = new LODGame(map);
}
catch(BindException e){
throw new Exception("Failed to create a server socket: "+
e.getMessage());
}
}
public void run() throws Exception {
final ServerSocket serverSocket = getServerSocket();
while (true){
System.out.println("Listening for a client on port: "+
serverSocket.getLocalPort());
// Wait for a client to make contact.
final Socket clientSocket = serverSocket.accept();
// Contact ...
System.out.println("A client has arrived.");
Thread serverThread = new Thread(){
public void run(){
boolean quit = false;
while (!quit){
try{
// Wrap the input stream in a BufferedReader.
BufferedReader reader = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
// Wrap the output stream in a BufferedWriter.
writer = new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream()));
game.setWriter(writer);
game.startNewGame();
// Read lines until the client terminates.
String request = reader.readLine();
while(request != null){
// Write the length of the line as a String.
playerCommand(request);
request = reader.readLine();
}
}
catch(IOException e){
System.out.println("IOException talking to the client: "+
e.getMessage());
}
finally{
if(clientSocket != null){
System.out.println("The client has gone.");
break;
// Close the socket to the client.
//try
// {
// clientSocket.close();
// }
//catch(Exception e)
// {
// System.out.println("Error" + e.getMessage());
// System.exit(1);
// }
}
}
try
{
serverSocket.close();
}
catch(Exception e)
{
System.out.println("Error" + e.getMessage());
System.exit(1);
}
}
}
};
serverThread.start();
}
}
protected ServerSocket getServerSocket(){
return serverSocket;
}
// The socket on which the listening is done.
private final ServerSocket serverSocket;
No this has nothing to do with the clientSocket being final. Your problem is that you are closing the serverSocket in the client thread. You should be closing the clientSocket only at the end of the thread:
while (!quit) {
try {
...
} catch(IOException e){
System.out.println("IOException talking to the client: "+
e.getMessage());
} finally {
...
clientSocket.close();
}
// DON'T DO THIS: serverSocket.close();
}
The serverSocket should only be closed if accept() throws an Exception -- it should not be touched by the client thread at all.

Categories

Resources