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.
Related
I have code which works with one client connection. What I need is ability for the server to handle multiple client requests using multithreaded approach.
I found some solutions, but it's not meet my requirements, like this, or this
Server.java
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server extends User {
private Socket clientSocket;
private ServerSocket serverSocket;
public Server() {
super();
}
private void createConnection() {
try {
InetAddress locIP = InetAddress.getByName("127.0.0.1");
serverSocket = new ServerSocket(9999, 0, locIP);
// serverSocket = new ServerSocket(4444, 4444, InetAddress.getByName("192.168.0.101"));
} catch (IOException e) {
System.err.println("Could not listen on port: 9999 ." + e);
System.exit(1);
}
}
private void closeConnection() {
try {
serverSocket.close();
} catch (IOException e) {
System.err.println(e);
}
}
#Override
public void connect() {
createConnection();
//Socket clientSocket=null;
try {
clientSocket = serverSocket.accept();
System.out.println("Client connected! "
+ "IP: "
+ clientSocket.getInetAddress()
+ ", port: "
+ clientSocket.getPort());
} catch (IOException e) {
System.err.println("Accept failed. " + e);
System.exit(1);
}
}
#Override
public void disconnect() {
try {
clientSocket.close();
} catch (IOException e) {
System.err.println(e);
}
closeConnection();
}
#Override
public Socket getSocket() {
return clientSocket;
}
#Override
public String toString() {
return new String("Server");
}
}
Client.java
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client extends User {
private Socket socket;
public Client() {
super();
}
#Override
public Socket getSocket() {
return socket;
}
#Override
public void connect() {
try {
InetAddress locIP = InetAddress.getByName("127.0.0.1");
// socket = new Socket(9999, 0, locIP);
// socket = new Socket("localhost", 9999); oryginalny
socket = new Socket(locIP, 9999);
} catch (UnknownHostException e) {
System.err.println("The host not found! " + e);
System.exit(1);
} catch (IOException e) {
System.err.println("Can't find connection! " + e);
System.exit(1);
}
}
#Override
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
System.err.println(e);
}
}
#Override
public String toString() {
return new String("Client");
}
}
SendButton.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JTextPane;
#SuppressWarnings("serial")
public class SendButton extends JButton {
private JTextPane incomingMessages;
private JTextPane messageToSend;
private User user;
public SendButton(User user, JTextPane incomingMessages, JTextPane messageToSend) {
super("Send!");
this.user = user;
this.incomingMessages = incomingMessages;
this.messageToSend = messageToSend;
this.addActionListener(new SendListener());
}
public class Write {
private PrintStream out;
public Write() {
try {
out = new PrintStream(new BufferedOutputStream(
user.getSocket().getOutputStream(), 1024), false);
} catch (IOException e) {
System.err.println(e);
}
}
public void send(String message) {
if (message != null) {
out.println(message);
out.flush();
incomingMessages.setText(new String(incomingMessages.getText() + "\nMe: " + message));
}
}
}
public class SendListener implements ActionListener {
private Write write = new Write();
private String toSend;
#Override
public void actionPerformed(ActionEvent event) {
toSend = messageToSend.getText();
if (toSend != null || event.getActionCommand() == "\n") {
write.send(toSend);
}
messageToSend.setText(new String(""));
}
}
}
You need to create a new Runnable class, whose data members consist of a Socket and its input and output streams. This class is used on the server side. Its run() method is responsible for all I/O to that client. Then your accept() loop just looks like this:
while (true)
{
new Thread(new ConnectionHandler(serverSocket.accept())).start();
}
where ConnectionHandler implements Runnable as above.
simply what you need to do is after accepting the request from the client (Using main thread), then the request pass to a new thread with the client socket and process the request inside the new thread. So the main thread is free to accept new requests.
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
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.
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); }
}}}
Before people suspect that I have no idea what I'm doing at all (and end up voting this down for no reason at all), please read this:
It connects to my server just fine! I'm getting no errors (from the client OR server), and my server is recognizing the connection. It works with my friend's client that he made, but I wanted to make my own client, and apparently I'm doing something wrong. PLEASE STAY ON TOPIC! Thanks :)
Title basically says it all. I've tested with println messages above and below the setupStream() in my Client.java run(), but only the message above the setupStream() prints. I'm not sure how I'm supposed to initialize my stream without making my program come to a halt.
Client.java
import java.io.IOException;
public class Client extends Stream implements Runnable {
public boolean running = false;
private Thread clientThread;
Frame frame;
public Client() {
super("localhost", 43594);
frame = new ClientFrame(500, 500);
start();
}
public synchronized void start() {
if(running) return;
running = true;
clientThread = new Thread(this);
clientThread.start();
}
public synchronized void stop() {
if(!running) return;
running = false;
clientThread.interrupt();
try {
clientThread.join();
} catch (InterruptedException e) {e.printStackTrace();}
}
public void run() {
try{
setupStream();
while(running) {
System.out.println("running");
}
}catch(IOException e) {
e.printStackTrace();
}finally {
try{
out.close();
in.close();
socket.close();
clientThread.join();
}catch(IOException | InterruptedException e) { e.printStackTrace(); }
}
}
public static void main(String[] args) {
new Client();
}
}
Stream.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Stream {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
String data;
public Stream(String host, int port) {
try {
socket = new Socket(host, port);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void setupStream() throws IOException {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
}
}
My Server Thread:
package Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
public class User extends Thread {
public static int users = 0;
public int ID;
public String username;
boolean online = false;
public static ArrayList<String> usernames = new ArrayList<String>();
Socket socket;
DataOutputStream out;
DataInputStream in;
String input;
public User(Socket socket) {
this.socket = socket;
}
public String decode(String input) {
String[] split = input.split(" ");
if(input.startsWith("::")) {
try {
switch(split[0].substring(2, split[0].length()).toLowerCase()) {
case "setname":
case "changename":
case "newname":
if(usernames.contains(split[1].toLowerCase())) {
out.writeUTF("This name is already taken! Please choose a different one.");
out.flush();
return null;
}
if(username == null) {
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
Server.users.put(split[1].toLowerCase(), Server.user[ID]);
usernames.add(split[1].toLowerCase());
} else {
usernames.remove(username.toLowerCase());
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
usernames.add(split[1].toLowerCase());
}
return null;
case "rank+":
return null;
case "[sm]=":
return null;
}
}catch(IOException e) { }
}
return input;
}
String timeStamp;
public void run() {
try {
out = new DataOutputStream(socket.getOutputStream());
out.flush();
in = new DataInputStream(socket.getInputStream());
while((input = in.readUTF()) != null) {
input = decode(input);
if(input != null) {
if(username != null) {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + username +": "+input);
} else {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + "Guest "+ID+": "+input);
}
}
}
}catch(IOException e) { e.printStackTrace(); } finally {
try{
out.close();
in.close();
socket.close();
} catch(IOException e) { e.printStackTrace(); }
}
}
}
I haven't touched the code of my Server Thread for a while, since it has always worked up until I made my new client.
I suspect that your server does not create an ObjectOutputStream, so when the client constructs its ObjectInputStream, it blocks waiting for the object stream header, which never arrives.