Java Socket Handling Clients Disconnecting [duplicate] - java

This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 7 years ago.
i am trying to make a chat program. The problem i am having is that my loop in the EchoThread always thinks that the connection is true. I have tried to use if(s.isConnected() == false) but that didn't work also i tried to do if(s.isClosed() == true) if you can help thank you in advance. Here is my code
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class server {
public ObjectInputStream input;
public ServerSocket server;
public Socket s;
public ObjectOutputStream output;
public ArrayList<ObjectOutputStream> outputs = new ArrayList<ObjectOutputStream>();
public ArrayList<Socket> users = new ArrayList<Socket>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
new EchoThread(s).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class EchoThread extends Thread {
private Socket s1;
public EchoThread(Socket s) throws IOException {
this.s1 = s;
}
public void run() {
users.add(s1);
try {
outputs.add(new ObjectOutputStream(s1.getOutputStream()));
newUser();
} catch (IOException e) {
System.out.println("Error 2");
}
while(s1.isConnected() == true) {
// loops until socket looses connection
}
System.out.println("Disconnected");
}
}
public class check implements Runnable {
public void run() {
}
}
public void newUser() {
try {
for(ObjectOutputStream o: outputs) {
o.writeObject(s.getInetAddress() + " Connected");
}
} catch (IOException e1) {
System.out.println("Error 21");
}
}
server() throws IOException {
Thread t = new Thread(new Accept());
t.start();
Thread ch = new Thread(new check());
ch.start();
}
public static void main(String[] args) throws IOException {
new server();
}
}

you have to read this, you have to check with the read()method to check if it returns -1.
https://stackoverflow.com/a/10241044/964152

while(s1.isConnected() == true) {
This is not a valid loop. isConnected() is true because you accepted the socket, and it doesn't magically become false afterwards. When the client disconnects, you will get the appropriate end of stream indication from whichever read method you're calling.

Related

why java tcp server is accepting closed socket?

I have a class A that accepts TCP connection and send this new socket to Thread B where data from that socket is received and sent.
Class A{
Class b = new B();
public void run()
{
b.start();
while(true){
Socket socket = serverSocket.accept();
if(socket==null || socket.isClosed())continue;
b.setSocket(socket);
}
}
}
Class B extends Thread{
Socket socket;
public void setSocket(Socket p_socket) throws IOException
{
if(socket!=null && !socket.isClosed())
{
try{
socket.close();
socket = null;
Thread.sleep(5);
}
catch(Exception ex)
{}
}
socket = p_socket;
inputStream = socket.getInputStream(); // Here I am getting socket.closed() exception very much.
}
This worked fairly good in the past but now recently I am very very frequently getting the following error.
java.io.IOException: Socket Closed
at java.net.AbstractPlainSocketImpl.getInputStream(AbstractPlainSocketImpl.java:421)
at java.net.Socket$2.run(Socket.java:914)
at java.net.Socket$2.run(Socket.java:912)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.Socket.getInputStream(Socket.java:911)
I don't understand why this is happening now after years of working fine. Is this due to the network problem or Thread related something?
Updated:
Can this be the server related problem? Because the same application is running on other server but they are not having this problem.
The whole setup concept looks a bit broken. You should not "change" resources from the outside, while maybe there is still some work going on in that thread. A way better concept is to encapsulate the Socket into a new worker thread:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class WrapHandler {
static public class Server {
private final ServerSocket mSocket;
private final ArrayList<Handler> mRunningHandlers = new ArrayList<>();
public Server(final int pPort) throws IOException {
mSocket = new ServerSocket(pPort);
new Thread(() -> mainLoop()).start();
}
private void mainLoop() {
while (true) {
try {
#SuppressWarnings("resource") final Socket socket = mSocket.accept(); // do not close, do not handle with resource, socket will be closed by handler!
final Handler h = new Handler(socket, this);
handlerStarted(h);
} catch (final IOException e) {
e.printStackTrace(); // do something useful
}
}
}
synchronized void handlerStarted(final Handler pHandler) {
mRunningHandlers.add(pHandler);
}
synchronized void handlerEnded(final Handler pHandler) {
mRunningHandlers.remove(pHandler);
}
void handleException(final Handler pHandler, final Throwable pException) {
/* again do something useful */
}
}
static public class Handler {
private final Socket mSocket;
private final Server mServer;
public Handler(final Socket pSocket, final Server pServer) {
mSocket = pSocket;
mServer = pServer;
new Thread(() -> handleSocket()).start();
}
private void handleSocket() {
try {
handleData();
} catch (final IOException e) {
mServer.handleException(this, e);
} finally {
mServer.handlerEnded(this);
stop();
}
}
private void handleData() throws IOException {
mSocket.getInputStream().read();
/* data handling code here */
}
void stop() {
try {
mSocket.close();
} catch (final IOException e) { /* ignore or handle as you will */ }
}
}
}

Socket java disconnect

I made this program and i have a problem. When a client disconnect the server crashes and i don't know how to solve this problem.
import java.io.*;
import java.net.*;
public class clientread extends Thread{
Socket sc;
public int ver=0;
public clientread(Socket sc)
{
this.sc=sc;
}
public void run()
{ BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
while(true){
try{
String mes=buf.readLine();
if(mes.equals("END"))
{
sc.close();
break;
}
if(mes!=null)
{
PrintStream ps=new PrintStream(sc.getOutputStream());
ps.println(mes);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
import java.net.*;
import java.io.*;
public class citireserver extends Thread{
Socket sock;
public citireserver(Socket sr)
{
sock=sr;
}
public void run()
{
while(true)
{
try{
BufferedReader buf=new BufferedReader(new InputStreamReader(sock.getInputStream()));
String mes=buf.readLine();
if(mes!=null)
System.out.println(mes);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
The first one reads a message from keyboard and transmit it to the server and the server transmit it to the rest of the clients and the second one reads everything transmitted from the server and print it. I thought to put in the first class a condition where if the client input "END" it will terminate but a don't know to end all of this.
This it the client class which access this two classes
import java.net.*;
public class client {
public static void disc(Socket sc)
{
try{
sc.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
try{
Socket sr=new Socket("192.168.0.105",1028);
new clientread(sr).start();
new citireserver(sr).start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
import java.net.*;
public class server {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("the server is running");
try{
ServerSocket sr=new ServerSocket(1028,100);
while(true)
{
new handler(sr.accept()).start();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
import java.io.*;
import java.util.*;
import java.net.*;
public class handler extends Thread {
public static ArrayList<Socket> sock=new ArrayList<Socket>();
Socket sc;
public handler(Socket sc)
{
this.sc=sc;
}
public void check()
{
if(!sc.isConnected())
{
for(int i=0;i<sock.size();i++)
if(sock.get(i)==sc)
sock.remove(i);
}
}
public void run()
{
sock.add(sc);
System.out.println("connected");
while(true)
{
try{
BufferedReader io=new BufferedReader(new InputStreamReader(sc.getInputStream()));
String ms=io.readLine();
System.out.println(ms);
if(ms.equals("END"))
{
break;
}
if(ms!=null)
{
Iterator<Socket> it=sock.iterator();
while(it.hasNext())
{
Socket vv=it.next();
PrintStream ps=new PrintStream (vv.getOutputStream());
ps.println(ms);
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
try{
sc.close();
check();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
I thought to put if in the first class after buf.readline and if the condition it true then sc.close and break. But it does nothing and i get a message probably because this socket is used in another thread in the second class and i don't know how to stop all of this. I get this error in the client which i close
java.net.SocketException: Socket is closed at
java.net.Socket.getInputStream(Socket.java:876) at
citireserver.run(citireserver.java:15)
Edit:After i resolved with the thread i get another
error:java.net.SocketException: Socket is closed
at java.net.Socket.getOutputStream(Socket.java:916)
at handler.run(handler.java:41)
This error appear after i disconnect one client and i think it comes from the fact that that socket is not removed from the arraylist and when it iterate it goes on that socket.Why it doesnt remove it? what is wrong with check()?
When readLine() returns null you should:
stop reading
exit the loop
close the socket.

Sending a String through socket. Server not receiving it

I've been struggling lately to find a way to deliver strings through a socket file. I'm planning to create a remote tool(client) to execute things based on the received message(server).
I've searched answers for my problem on google and i found some things and managed to understand things but I also got some problems (i'm new to programming, not yet in college).
I would appreciate any help in this matter
SocketService.java ---- class file = serverside
package socket;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;
public class ServiceSocket {
static ServerSocket myService;
static Socket thesocket;
static Thread socketThread;
public static boolean socketRunning;
public static DataInputStream socketMessage;
public static void initialise(String localhost, int portNumber ){
// make a server socket//////
try {
myService = new ServerSocket(portNumber);
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
//////////////////////////////
}
public static void deploySocket(){
socketThread = new Thread() {
public void run(){
// making connection
System.out.println("VVaiting for connection...");
try {
thesocket = myService.accept();
System.out.println("Connection made");
socketRunning = true;
} catch (IOException e) {
e.printStackTrace();
}
////////////////////////////////////
try {
StartBrain();
} catch (IOException e1) {
e1.printStackTrace();
}
if(socketRunning = false) {
try {
thesocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
socketThread.start();
}
public static String getSocketMessage() throws IOException {
try {
socketMessage = new DataInputStream(thesocket.getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
boolean looprunning = true;
String message = null;
System.out.println("entering loop");
do {
try {
while (socketMessage.readUTF() != null) {
message = socketMessage.readUTF();
looprunning = false;
}
} catch (EOFException e) {
}
}while(looprunning);
System.out.println("Message received from UTF: " + message);
System.out.println("loop exited vvith message");
if(message == null) {
message = "no message";
}
return message;
}
public static void StartBrain() throws IOException {
System.out.println("socket brain started");
String BrainMessage = getSocketMessage();
if(BrainMessage == "command") {
System.out.println("Command EXECUTED HAHA");
} else if(BrainMessage == "taskschedule") {
System.out.println("task scheduled");
} else {
System.out.println("no command received");
}
}
Main.java ----- class file = serverside
package main;
import socket.ServiceSocket;
public class Main {
public static void main(String[] args) {
ServiceSocket.initialise("localhost", 3535);
ServiceSocket.deploySocket();
}
}
}
Main.java = CLIENT
package mainPackage;
import java.io.*;
import java.net.*;
import java.util.concurrent.TimeUnit;
public class Main {
private static Socket clientSocket;
public static void sendMessage(String message) throws IOException, InterruptedException {
DataOutputStream dOut = new DataOutputStream(Main.clientSocket.getOutputStream());
dOut.writeUTF(message);
dOut.flush();
dOut.close();
}
public static void main(String[] args) throws Exception {
// String modifiedSentence;
clientSocket = new Socket("localhost", 3535);
System.out.println("Initializing");
sendMessage("command");
boolean running = true;
while(running) {
TimeUnit.SECONDS.sleep(3);
sendMessage("taskschedule");
}
clientSocket.close();
}
}
main problem
do {
try {
while (socketMessage.readUTF() != null) {
message = socketMessage.readUTF();
looprunning = false;
}
} catch (EOFException e) {
}
}while(looprunning);
it doesn't read the string/UTF
It does read it, here:
while (socketMessage.readUTF() != null) {
and then throws it away as you're not assigning the return-value to a variable, and then tries to read another one, here:
message = socketMessage.readUTF();
but the one (first) message you send is already gone.
You have problem in
while (socketMessage.readUTF() != null) {
message = socketMessage.readUTF();
looprunning = false;
}
First call to method readUTF() will block thread and read UTF string from socket, but you discard this value and try read string second time.
If you replace socketMessage.readUTF() != null with looprunning server will log this messages:
VVaiting for connection...
Connection made
socket brain started
entering loop
Message received from UTF: command
loop exited vvith message
no command received
P.S.
Command is not recognized because use compare objects (string is object) with ==, but you must use equals.
public static void StartBrain() throws IOException {
System.out.println("socket brain started");
String BrainMessage = getSocketMessage();
if (BrainMessage.equals("command")) {
System.out.println("Command EXECUTED HAHA");
} else if (BrainMessage.equals("taskschedule")) {
System.out.println("task scheduled");
} else {
System.out.println("no command received");
}
}
Server log:
VVaiting for connection...
Connection made
socket brain started
entering loop
Message received from UTF: command
loop exited vvith message
Command EXECUTED HAHA

Socket Client/Server stop method in java

This is the simple client/server socket app for my faculty project. First, the Server class should be run, and then if Client class runs - it prints out the IP address of the local machine and the port that's been used.
I can't figure out one thing:
How and WHERE to create a method in class that will close(stop) the Server? And
how to make this like an event or something, for example if client
sends "stop" it should somehow stop the server...
SERVER.JAVA
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) {
System.out.println("The server has been summoned.\n");
System.out.println("The server is waiting for client to come...");
try {
ServerSocket servertest = new ServerSocket(2014);
while (true) {
try {
Socket ser = servertest.accept();
new ThreadSer(ser).start();
} catch (IOException e) {}
}
} catch (IOException e) {System.err.println(e);}
}
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
OutputStream out = s.getOutputStream();
out.write(response.getBytes());
} catch (IOException e) { System.err.println(e); }
}}}
CLIENT.JAVA
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 2014);
new OutputThread(socket.getInputStream()).start();
}
public static class OutputThread extends Thread {
private InputStream inputstream;
public OutputThread(InputStream inputstream) {
this.inputstream = inputstream;
}
#Override
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(inputstream));
while (true) {
try {
String line = input.readLine();
System.out.println(line);
} catch (IOException exception) {
exception.printStackTrace();
break;
}
}
}}}
You should constantly ask for the inputstream of the client.. put it in the loop that always accept for the client input..
example:
public static class ThreadSer extends Thread {
private Socket s;
public ThreadSer(Socket s) {
this.s = s;
}
#Override
public void run() {
try {
String response = "This is the IP: " + s.getLocalAddress() + " that has come via port: "
+ s.getLocalPort() + "\r\n";
ObjectInputStream input = new ObjectInputStream(s.getInputStream());
while(true)
{
Object object = input.readObject();
if(object instanceof String)
{
String command = ((String) object).trim();
if(command.equals("stop"))
break;
}
}
s.close();
} catch (IOException e) { System.err.println(e); }
}}}

java rxtx SerialWriter issue

I am using RXTX to communicate between JAVA and a microcontroller.
This is the JAVA code for opening a connection, sending and receiving data
package app;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class SerialCommunication1 {
private static SerialCommunication1 instance = null;
private static boolean coonected = false;
public static SerialCommunication1 getInstance(){
if(instance == null)
instance = new SerialCommunication1();
return instance;
}
private SerialCommunication1() {
super();
try {
connect("COM4");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SerialCommunication1.coonected = true;
}
void connect(String portName) throws Exception {
CommPortIdentifier portIdentifier = CommPortIdentifier
.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(this.getClass().getName(),
2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_2, SerialPort.PARITY_NONE);
InputStream in = serialPort.getInputStream();
OutputStream out = serialPort.getOutputStream();
(new Thread(new SerialReader(in))).start();
(new Thread(new SerialWriter(out))).start();
} else {
System.out
.println("Error: Only serial ports are handled by this example.");
}
}
}
/** */
public static class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
byte[] buffer = new byte[1024];
int len = -1;
try {
while ((len = this.in.read(buffer)) > -1) {
System.out.print(new String(buffer, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** */
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
System.out.println("Will try to execute");
try {
if(str.length() > 0){
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And this is the Java code that is calling when an event triggers
SerialCommunication1.getInstance();
if(ledStatus == true) {SerialCommunication1.SerialWriter.str = "4A01";}
else {SerialCommunication1.SerialWriter.str = "4A00";}
stopProcess();
And now the problem. I need to send a command to my microcontroller with the code 4A01 and, after receiving the answer, I need to call it again with the code 4A00. The calls are triggered by a button from my Java interface. The problem is that the second call is not executed (4A00 is not sending). I tried to inverse the command codes and they work well. After the first one (4A01) is executed, my microcontroller reacts and sends the response which is read by java and my interface is updated. When I send the invers command (4A00) it stops exactly at this line SerialCommunication1.SerialWriter.str = "4A00"; and doesn't even enter inside the SerialWriter's run() method.
Do you have any idea why is this happening? From the side of my microcontroller there is no problem, I checked all the possibilities with a tool.
I hope I made myself clear.
Thank you!
LE: I forgot to tel you that it didn't throw any errors or exceptions
I'm not sure because I'm not able to test your code but I think your problem is in SerialWriter class:
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null; // Here str is initialized to null
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
System.out.println("Will try to execute");
try {
if(str.length() > 0) { // this should throw NPE because str is null
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Since there is no loop in this method, then the thread created within SerialCommunication1 at this line:
(new Thread(new SerialWriter(out))).start();
most likely finishes its execution after sending the first str.
Honestly I don't understand how does it even send a single string, since str is initialized to null in first place and it should throw NullPointerException at str.length() line.
I would suggest you this approach:
Don't trigger a writer thread when connection is established, just trigger a new one every time a message will be sent.
Use Singleton pattern correctly.
Keep a reference to the serial port in SerialCommunication1 class.
Translated to code it would be something like this:
class SerialWriter implements Runnable {
OutputStream out;
String message;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void setMessage(String msg) {
this.message = msg;
}
public void run() {
try {
if(message != null) {
this.out.write(str.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then in SerialCommunication1 class add this public method:
public void sendMessage(String msg) {
SerialWriter writer = new SerialWriter(serialPort.getOutputStream()); // of course you'll have to keep reference to serialPort when connection is established
writer.setMessage(msg);
(new Thread(writer)).start();
}
And finally call this method in this way:
SerialCommunication1.getInstance().sendMessage("4A01");
tzortzik,
I think tha is a timeout problem. Try to addding a delay to writer :
/** */
public static class SerialWriter implements Runnable {
OutputStream out;
static String str = null;
public SerialWriter(OutputStream out) {
this.out = out;
}
public void run() {
Thread.sleep(500); //<----------- this should be in mainThread before to SerialWriter.start();
System.out.println("Will try to execute");
try {
if(str.length() > 0){
this.out.write(str.getBytes());
str = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
It happens to me many times, "we should learn to wait for a response" (^_^)
Check if you are executing well a secuence like the next:
Send command 4A01
Receive response 4A01 from micro
WAIT FOR RESPONSE BEFORE SEND SECOND COMMAND. Thread.sleep(500); //wait for 500 milis or more
Send command 4A00
Receive response 4A00 from micro
I hope it could help you.

Categories

Resources