How do I reconnect a client when server is down in Java? - java

I have a server that accepts sockets from whenever a client connects. I want to be able to shutdown my local server and let my client try to reconnect for about 5 times, and if I start my server the client should indicate that you have reconnected again.
I understand somewhat that this is done in the try{} catch(IOException){Here goes the code for handleing reconnect} I want to use the same socket that I first used to connect. I don't want to create a new Client cause then I have to enter username and stuff like that all over again
I tried to creating a new socket like clientSocket = new Socket("localhost", portnr) but I don't know if this is the correct way to go. If you have examples that answers this please link them. I dont mind reading as long as it is good documented. Thanks in advance!
EDIT.
Here is my Client Class
public class Client {
public static void main(String[] args) {
Client client = new Client();
client.connect();
}
//------------------------------------------------------------
//METHOD CONNECT
//------------------------------------------------------------
private void connect(){
int reConnectTries = 0;
Socket clientsocket;
try {
//------------------------------------------------
//Sets up variables needded for execution
clientsocket = new Socket("localhost", 8900);
DataOutputStream OUT = new DataOutputStream(clientsocket.getOutputStream());
ListenforMessages listen = new ListenforMessages(clientsocket);
//We don't want to enter username all the time
//So this goes not in the while-loop
//------------------------------------------------
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter username");
String username = keyboard.nextLine();
//Sends username to sever so it can be added to a list
OUT.writeUTF(username);
//------------------------------------------------
//------------------------------
//Creates a thread to listen on messages from server(Other clients in this case)
Thread trd = new Thread(listen);
trd.start();
//------------------------------
while (true) {
try {
String sendMessage = keyboard.nextLine();
OUT.writeUTF(sendMessage);
OUT.flush();
} catch (Exception e) {
System.err.println("Could not send message to server. " + e);
}
}
} catch (IOException e) {
System.err.println("Couldnt establish a connection: " + e);
}
}
//------------------------------------------------------------
//CLASS FOR HANDLEING INPUT. We create a class for input on a new thread
//This is cause we don't want it to block other processes.
//----------------------------------------------------------------
class ListenforMessages implements Runnable{
Socket mySocket;
DataInputStream IN;
public ListenforMessages(Socket X) throws IOException {
this.mySocket = X;
}
#Override
public void run() {
try {
IN = new DataInputStream(mySocket.getInputStream());
while (true) {
System.out.println(IN.readUTF());
}
} catch (Exception e) {
System.err.println("Couldn't fetch message from server.Error: " + e);
}
}
}
}

There's a couple of solutions to this problem, but a simple one would to be have the client try to reconnect (open a new connection to the server) at set intervals. For example, you could try something like this to have your client try to reconnect once every 3 minutes:
while(true) {
try {
clientSocket = new Socket("localhost", portnr);
break; // We connected! Exit the loop.
} catch(IOException e) {
// Reconnect failed, wait.
try {
TimeUnit.MINUTES.sleep(3);
} catch(InterruptedException ie) {
// Interrupted.
}
}
}
This way, the client will try to connect, and if it fails, wait for 3 minutes before trying again.

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.NoRouteToHostException;
import java.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.net.ConnectException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
final class TCPClient{
private static Scanner in ;
private static DataOutputStream douts;
private static OutputStream outs;
private static InputStream ins;
private static DataInputStream dins;
private static String ip;
private static Integer port;
private int count = 0;
private static int times;
public TCPClient(){
serverConTest(port);
}
private boolean portIsOpenOrNot(String ip, int port){
try{
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip,port),500);
socket.close();
return true;
}catch(Exception e){
}
return false;
}
private void serverConTest(int port){
while(true){
try{
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr,port);
Socket socket = new Socket();
System.out.println("Connecting To server...");
socket.connect(sockaddr);
Thread.sleep(1000);
boolean isactive = true;
if(portIsOpenOrNot(ip,port)){
outs = socket.getOutputStream();
douts = new DataOutputStream(outs);
System.out.println("Sending Request to server:");
while(isactive){
Thread.sleep(1000);
douts.writeUTF("Are you Alive..!");
ins = socket.getInputStream();
dins = new DataInputStream(ins);
System.out.println("Response from server : "+dins.readUTF());
}
}
}catch(SocketException e){
System.out.println("Connection lost");
}catch(IOException e){
break;
}catch(InterruptedException e){
System.out.print("connection timeout in 50 second.");
break;
}
}
}
public static void main(String[] args){
in = new Scanner(System.in);
System.out.print("Enter ip : ");
ip = in.nextLine();
System.out.print("Enter Port : ");
port = Integer.parseInt(in.next());
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(new Runnable() {
public void run() {
new TCPClient();
}
});
try{
future.get(50, TimeUnit.SECONDS);
}catch(InterruptedException e){
}catch(ExecutionException e){
}catch(TimeoutException e){
executorService.shutdownNow();
}
}
}
This sample will give you the complete understanding that when the server restarts then client will reconnects.

I didnt read all your code but this one is working for me
And dont forget to add the Server class and the method send that sends messages...
Client :
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
static Socket sock=null;
static DataInputStream in=null;
static DataOutputStream out=null;
static boolean connected=false;
static String currentip="";
static int currentport=0;
static void refreching(){
try {
in=new DataInputStream(sock.getInputStream());
out=new DataOutputStream(sock.getOutputStream());
Thread gg=new Thread() {
String msg="";
public void run() {
while(connected) {
try {
msg=in.readUTF();
System.out.println(msg);
} catch (IOException e) {
connected=false;
System.out.println("Reconnecing...");
while(!connected)
connect(currentip,currentport);
}
}
}
};
gg.start();
}
catch(Exception e) {
System.out.println("Problem while reading incoming and outgoing"+
"messages!");
connected=false;
}
}
static void connect(String iphost, int port){
try{
sock=new Socket(iphost,port);
currentip=iphost;
currentport=port;
connected=true;
refreching();
System.out.println("Connected!");
}
catch(Exception e){
System.out.println("Cant connect !");
connected=false;
}
}
public static void main(String[] args) {
connect("127.0.0.1",1234); //Example you can enter another's computer ip
//adress if connected to the same network !!!
//Send(Message_To_Server); Dont forget to add the sending code!!!
//Maybe i'll upload a video one day==>how to create a chat application
}

Related

Why my java multicast clientserver chat work with only one client at the time?

as I said, i'm tring to do a chat for sevral clients, and one server in java. However, it seems that only one client at the time can connect on the server, and I really don't know why (i'm a begginer in this field).
I have 4 classes, here are they :
MainClient :
package Multicast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class MainClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 5000)){
BufferedReader input = new BufferedReader(new java.io.InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
Scanner scanner = new Scanner(System.in);
String userInput;
String reponse;
String clientName = "none";
ClientThread clientThread = new ClientThread(socket);
clientThread.start();
do {
if(clientName.equals("none")) {
System.out.println("please enter your name");
userInput = scanner.nextLine();
clientName = userInput;
output.println(userInput);
}
else {
String message = ("|"+clientName +"| :");
//System.out.println(message);
userInput = scanner.nextLine();
output.println(message + " " + userInput);
if (userInput.equals("exit")) {
break;
}
}
}while (!userInput.equals("exit"));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientThread :
package Multicast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientThread extends Thread{
private Socket socket;
private BufferedReader input;
public ClientThread(Socket s) throws IOException {
this.socket = s;
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
#Override
public void run() {
try {
while(true) {
String reponse = input.readLine();
System.out.println(reponse);
}
}
catch(IOException e){
e.printStackTrace();
}
finally {
try {
input.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}
MainServer :
package Multicast;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MainServeur {
public static void main(String[] args) {
ArrayList<ServerThread> threadList = new ArrayList<>();
try(ServerSocket serverSocket = new ServerSocket(5000)){
Socket socket = serverSocket.accept();
ServerThread serverThread= new ServerThread(socket, threadList);
threadList.add(serverThread);
serverThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
and ServerThread :
package Multicast;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class ServerThread extends Thread{
private Socket socket;
private ArrayList<ServerThread> threadList;
private PrintWriter output;
public ServerThread(Socket socket, ArrayList<ServerThread> threads) {
this.socket = socket;
this.threadList = threads;
}
#Override
public void run() {
try {
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(socket.getOutputStream(), true);
while(true) {
String outputString = input.readLine();
if(outputString.equals("exit")) {
break;
}
printToAllClients(outputString);
System.out.println("Server received : " + outputString);
}
}
catch(Exception e) {
System.out.println("error occured in main of server : "+ e.getStackTrace());
}
}
private void printToAllClients(String outputString) {
for(ServerThread sT : threadList) {
sT.output.println(outputString);
}
}
}
when i try to connect a second client, this error occurs :
java.net.BindException: Cannot assign requested address: connect
at java.base/sun.nio.ch.Net.connect0(Native Method)
at java.base/sun.nio.ch.Net.connect(Net.java:579)
at java.base/sun.nio.ch.Net.connect(Net.java:568)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at java.base/java.net.Socket.connect(Socket.java:583)
at java.base/java.net.Socket.<init>(Socket.java:507)
at java.base/java.net.Socket.<init>(Socket.java:287)
at Multicast.MainClient.main(MainClient.java:13)
I followed this tutorial, thanks a lot and sorry if the post is too long.
Edit : My problem is solved, here are the changes :
package Multicast;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MainServeur {
public static void main(String[] args) {
ArrayList<ServerThread> MyThread = new ArrayList<>();
try (ServerSocket serverSocket = new ServerSocket(5000)) {
for (;;) {
Socket socket = serverSocket.accept();
ServerThread s = new ServerThread(socket, MyThread);
MyThread.add(s);
s.start();
}
} catch (IOException e) {
e.printStackTrace();;
}
}
}
You should have one ServerSocket that accepts one client after another in a loop,
on the specified port 5000.
The session then is handled in an other thread, so the next client can be accepted (waited upon).
public class MainServeur {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(5000)) {
for (;;) {
Socket socket = serverSocket.accept();
new ServerThread(socket).start();
}
} catch (IOException e) {
System.getLogger(MainServeur.class.getName()).error(e);
}
}
}
Rather than elementary using a Thread, you can use ExecutorServices.
ThreadPoolExecutor executor = (ThreadPoolExecutor) executors.newFixedThreadPool(50);
That goes beyond the question asked, but allows thread pools limiting the number of clients, wait for all threads to end and more.

Server doesn't forward message to all in the chat

i am trying to create a simple chat app using java sockets, the server is threaded, when a client connects its socket is added to an ArrayList, so that i can send to all in that list.
the problem is when 3 clients are connected, the for loop that sends doesn't work properly, for ex : client 0 sends to both 1 and 2 but client 2 doesn't send to anyone :(
The server and the ClientHandler :
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
public class MainServer {
private static int portnumber = 6968;
static ArrayList <ClientHandler> allClients = new ArrayList<>();
public static void main(String[] args) throws Exception {
// init
// server works by default on localhost
ServerSocket serversocket = new ServerSocket(portnumber);
int clientNo = 0;
System.out.println("server is running on port : " + portnumber);
while (true) {
// creating a socket for each connection
Socket clientsocket = null;
try {
// receiving incoming requests from users/clients
clientsocket = serversocket.accept();
// input and output from client
PrintWriter out = new PrintWriter(clientsocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientsocket.getInputStream()));
// create a threads
ClientHandler ch = new ClientHandler(clientsocket, "Client#" + clientNo, in, out);
// adding to the clientList
allClients.add(ch);
System.out.println(ch.clientName + " has joined");
Thread clientThread = new Thread(ch);
clientThread.start();
// decrease when user leaves
clientNo++;
} catch (Exception e) {
clientsocket.close();
e.printStackTrace();
System.exit(1);
//out.close();
//in.close();
//clientSocket.close();
//serverSocket.close();
}
}
}
}
// handle client requests
public class ClientHandler implements Runnable{
public String clientName;
public Socket clientsocket = null;
public boolean active = false;
private BufferedReader inp;
private PrintWriter out;
private final String EXIT_STR = "exit";
public Scanner clientSc = new Scanner(System.in);
public ClientHandler(Socket socket, String name, BufferedReader inp, PrintWriter out) {
this.clientsocket = socket;
this.clientName = name;
this.inp = inp;
this.out = out;
// active when the thread is created
this.active = true;
}
#Override
public void run() {
// getting the output temp
String recivedMsg = "";
while (true) {
try {
recivedMsg = inp.readLine();
System.out.println(recivedMsg);
// check for ctrl+C
if (recivedMsg.equals(this.EXIT_STR)){
// send to all
System.out.println(this.clientName + " exits");
// close the connection and break
this.active = false;
this.clientsocket.close();
// bye
break;
}
// send to all except me
for (ClientHandler client : MainServer.allClients){
if (!client.clientName.equals(this.clientName)){
client.out.println(this.clientName + ":" + recivedMsg);
client.out.flush();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
// clean
this.clientsocket.close();
this.inp.close();
this.out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The client :
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private String hostName;
private int portNumber;
// set connction and server
public PrintWriter out = null;
public BufferedReader in = null;
public Socket clientSocket = null;
Client(String hostName, int port) {
this.hostName = hostName;
this.portNumber = port;
// setting the connction
this.setConnection();
}
private void setConnection () {
try {
this.clientSocket = new Socket(this.hostName, this.portNumber);
this.out = new PrintWriter(this.clientSocket.getOutputStream(), true);
this.in = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public void sendMessageToServer(String msg) {
//System.out.println("The msg is : " + msg);
out.println(msg);
}
public String readMessage() {
String outputMsg = "";
try {
outputMsg = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return outputMsg;
}
// shit cleaning
public void closeSession(){
try {
this.out.close();
this.in.close();
this.clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
System.out.println("Session has been terminated!");
}
public static void main(String args[]) throws IOException{
// init
String host = "localhost";
int port = 6968;
Client newClient = new Client(host, port);
// // send a message
Scanner sc = new Scanner(System.in);
Thread sendMsg = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
String userInput = sc.nextLine();
newClient.sendMessageToServer(userInput);
if (userInput.equals("exit")) {
System.exit(1);
}
} catch (Exception e) {
System.exit(1);
}
}
}
});
Thread getMsg = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
String msgRead = "";
try {
msgRead = newClient.readMessage();
System.out.println(msgRead);
} catch (Exception e) {
System.exit(1);
}
}
}
});
sendMsg.start();
getMsg.start();
}
}
I think the problem is here :
// send to all except me
for (ClientHandler client : MainServer.allClients){
if (!client.clientName.equals(this.clientName)){
client.out.println(this.clientName + ":" + recivedMsg);
client.out.flush();
break;
}
}
The fix is straightforward: remove the break statement from the loop where you think the problem is.
This break statement causes the loop through all the ClientHandlers to stop as soon as it sends the message to one client. You don't want this: you want this loop to keep going and send the message to all clients other than the one that wrote the message.

In java socket programming chat application, Is it possible to create a individual chat for each clients like whatsapp?

Now I'm done with the application which have the server and client, server accepts the client request and add the client object into the Arraylist and starts a new thread for each clients. when multiple clients connects, clients can list all the clients, and they can send a message to any clients in the list. For example client1, client2, client3 connects to the server client1 and client2 sending a message to the client3,It will be printed in client3 console. all working fine. Now i need to add additional feature that each clients sends a message in individual chat, if client1 opens a chat with client2 the conversation between those two clients only should be displayed, not client3 messages, and vice versa. To do that implementation do i need any additional concept like multi threading. I'm not asking a source code, I'm just asking a idea to implement the above feature.
Can anyone tell me the suggestion or reference to implement separate chats for different clients... Need to keep the old messages until the server goes offline?
Server.java
package server;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.*;
import java.util.Vector;
public class Server {
static Vector<ClientHandler> AllClients = new Vector<ClientHandler>();
public static void main(String args[]) throws Exception {
try {
ServerSocket ss = new ServerSocket(1111);
System.out.println("Server Started");
while(true) {
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String clientname = dis.readUTF();
System.out.println("Connected With : "+clientname);
ClientHandler client = new ClientHandler(s,clientname);
Thread t = new Thread(client);
AllClients.add(client);
t.start();
System.out.println("Ready to accept connections...");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientHandler.java
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;
public class ClientHandler extends Thread{
private DataInputStream in;
private DataOutputStream out;
private String ClientName;
private boolean login;
private Socket Socket;
Scanner sc = new Scanner(System.in);
ClientHandler(Socket s,String name) throws Exception{
this.in = new DataInputStream(s.getInputStream());
this.out = new DataOutputStream(s.getOutputStream());
this.login = true;
this.ClientName = name;
this.Socket = s;
}
public void run() {
while(true) {
try {
String received = in.readUTF();
if(received.equalsIgnoreCase("logout")) {
this.login = false;
this.out.writeUTF("logout");
int i;
for(i = 0; i < Server.AllClients.size(); i++) {
if(this.ClientName.equals(Server.AllClients.get(i).ClientName))
break;
}
Server.AllClients.remove(i);
System.out.println(this.ClientName+" logged out");
this.Socket.close();
break;
}
if(received.equalsIgnoreCase("getlist")) {
for(int i = 0; i < Server.AllClients.size(); i++) {
out.writeUTF(i+1 +", "+Server.AllClients.get(i).ClientName);
}
continue;
}
if(received.contains(",")) {
String[] Message = received.split(",");
for(ClientHandler c : Server.AllClients) {
if(c.ClientName.equalsIgnoreCase(Message[1]) && c.login) {
c.out.writeUTF(this.ClientName +" : "+ Message[0]);
c.out.flush();
break;
}
}
}
}catch(Exception e) {
System.out.println("Error :"+e.getMessage());
}
}
try {
this.in.close();
this.out.close();
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
Client.java
package client;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
static DataInputStream dis;
static DataOutputStream dos;
static Socket s;
public static void main(String args[])throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("Enter Cient Name : ");
String name = sc.nextLine();
s = new Socket("localhost",1111);
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(name);
Thread sendMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (true) {
String msg = sc.nextLine();
try {
dos.writeUTF(msg);
if(msg.equalsIgnoreCase("logout")) {
System.out.println("Logged out");
break;
}
} catch (IOException e) {
System.out.println("Error in send method :"+e.toString());
}
}
}
});
Thread readMessage = new Thread(new Runnable()
{
#Override
public void run() {
while (true) {
try {
String msg = dis.readUTF();
if(msg.equalsIgnoreCase("logout")) {
System.out.println("Logged out");
break;
}
System.out.println(msg);
} catch (IOException e) {
System.out.println("Error in read method :"+e.getMessage());
}
}
}
});
sendMessage.start();
readMessage.start();
}
}
If my code have any irrelevant statements please do suggest a better way to optimise the code
The first answer is: yes it is possible.
The second answer: it's not about threading, you have to think in the first place (it's important, but not in the frist place).
the third answer: as i understand your code, the main data-structre is the collection of clients and their handler. In my opinion there is a further abstraction-layer missing in between.
In the frist place think about a data structure like "chatRoom". A client connecting to server has to send a "chatRoom"-name to the the server. Than the server creates the chatRoom or adds the client to the chatRooom's client-set. From that point a client can send his messages to the chatRoom not to the client directly anymore.
In a further step: To enable sending messages to inidividual clients you can e.g. enforce a chatRoom for every pair of clients (take care: this can be very expansive), so individual communication between clients is still possible.

java network programming TCP chat full duplex

I'm implementing a simple tcp chat between a server and a client. I'm using multi-threading so as the server and the client can send and receive data at the same time (full duplex). The program works but if the server has a console for both typing the sending message and also displaying receiving message (same case for client), I cannot edit my typed message that should be sent to server or client when a message has been received from the other side. For e.g:
run(server console):
input msg to send client:
you:
client: hi server
client: bye server.
For this example, i've typed a message to send to client while the client has already said hi server bye server. Before receiving from client, i see what i've typed but after receiving, I can't see the msg nor edit it.
I can only use console because im not good with GUI and i want the same console for both sending and receiving data.
The codes for the program are shown below.
import java.net.*;
import java.io.*;
import java.util.Scanner;
public class ThreadServerSend implements Runnable {
String d;
Socket s1 = null;
Scanner sc = new Scanner(System.in);
public ThreadServerSend(Socket s)
{
s1=s;
}
public void run()
{
System.out.println("input msg to send client: ");
while (true){
try{
PrintStream p = new PrintStream(s1.getOutputStream());
System.out.println("you: ");
d=sc.nextLine();
p.println(d);
if (d.charAt(d.length()-1)=='.'){
s1.close();
break;}
}
catch(IOException e){}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class ThreadServerReceive implements Runnable {
String m;
Socket s2 = null;
Scanner sc = new Scanner(System.in);
public ThreadServerReceive(Socket s)
{
s2=s;
}
public void run()
{
while (true){
try{
BufferedReader b = new BufferedReader(new InputStreamReader(s2.getInputStream()));
m = b.readLine();
System.out.println("client: "+m);
if (m.charAt(m.length()-1)=='.'){
s2.close();
break;}}
catch(IOException e){}
}
}
}
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
public static void main(String[] args) throws UnknownHostException, IOException{
// TODO Auto-generated method stub
ServerSocket s = new ServerSocket(444);
Socket s1 = s.accept();
new Thread(new ThreadServerSend(s1)).start();
ServerSocket s4 = new ServerSocket(443);
Socket s2=s4.accept();
new Thread(new ThreadServerReceive(s2)).start();
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class ThreadClientSend implements Runnable {
String d;
Socket s1 = null;
Scanner sc = new Scanner(System.in);
public ThreadClientSend(Socket s)
{
s1=s;
}
public void run()
{
System.out.println("Input msg to send server: ");
while (true){
try{
PrintStream p = new PrintStream(s1.getOutputStream());
System.out.println("you: ");
String d = new Scanner(System.in).nextLine();
p.println(d);
if (d.charAt(d.length()-1)=='.'){
s1.close();
break;}
}
catch(IOException e){}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class ThreadClientReceive implements Runnable {
String m;
Socket s1 = null;
Scanner sc = new Scanner(System.in);
public ThreadClientReceive (Socket s)
{
s1=s;
}
public void run()
{
while (true){
try{
BufferedReader b = new BufferedReader(new InputStreamReader(s1.getInputStream()));
m= b.readLine();
System.out.println("Server: "+m);
if (m.charAt(m.length()-1)=='.')
{
s1.close();
break;
}
}
catch(IOException e){}
}
}
}
import java.io.*;
import java.net.*;
import java.util.*;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException{
// TODO Auto-generated method stub
Socket s1= new Socket("localhost",444);
Socket s2 = new Socket("localhost",443);
new Thread(new ThreadClientReceive(s1)).start();
new Thread(new ThreadClientSend(s2)).start();
}
}
A bit late, but I actually came up with a working version of this chat client for my programming class. I thought I might as well post it here. I used TCP (full duplex) with multithreading, and I got it to work in console. The small problem is that you can't see your own name (because console has only one active line), but otherwise it works pretty well.
Server (client is more or less the same, obviously the Sockets are normal sockets, not ServerSockets):
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.io.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
#SuppressWarnings("serial")
public class serverProgII extends Thread
{
private static ObjectOutputStream oos;
private static ObjectInputStream ois;
private static Socket connection;
private static ServerSocket server;
private static String ip, clientIP, textin, exitword ="exit";
private static networkmessage nmessage;
private static boolean connected = false;
private static boolean done = false;
private static String myName = "";
private static int counter = 0;
public static boolean started = false;
public String type;
public static void main(String[] args)
{
try {
BufferedReader brin = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter your name:> "); //send prompt to DOS window
myName = brin.readLine(); //read in user input
setupConnection();
setupStreams();
started = true;
} catch (Exception e) {
System.out.println("Problem setting up streams and connection!");
}
serverProgII sender = new serverProgII("sender");
serverProgII receiver = new serverProgII("receiver");
sender.start();
receiver.start();
}
public serverProgII(String t)
{
super();
type = t;
}
public void run() {
while(started) {
switch(type) {
case "sender":
sender();
break;
case "receiver":
receiver();
break;
}
try {
Thread.sleep(500); //milliseconds
} catch(Exception e){}
}
}
/* runServer()
This is where all the actual work gets done.
*/
public void sender()
{
try {
BufferedReader inn = new BufferedReader(new InputStreamReader(System.in));
textin = inn.readLine();
sendData(textin);
if (textin.equals(exitword)) // if "exit" is typed in shutdown the server.
{
started = false;
serverShutdown();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public void receiver() {
try {
getData();
} catch(Exception e) {
System.out.println("Error getting data");
}
}
//setup connection
public static void setupConnection() throws IOException
{
System.out.println("SERVER MODE ACTIVATED");
server = new ServerSocket (8000); //create the socket at port 8000
System.out.println("Waiting For Connection...");
connection = server.accept(); //wait for a connection
System.out.println("Received connection: "+connection.getInetAddress());
clientIP=""+connection.getInetAddress(); //print out the client IP address
}//setupconnection()
//Setup streams connection
public static void setupStreams() throws IOException
{
//Open up Streams
System.out.println("Streams Setup");
oos=new ObjectOutputStream(connection.getOutputStream()); //construct object output stream
ois=new ObjectInputStream(connection.getInputStream());
oos.flush();
}//setupStreams()
//method to write/send network data
public void sendData(String toSend) throws IOException
{
try
{
nmessage = new networkmessage(myName, toSend);
oos.writeObject(nmessage);
}//try
catch (IOException ioException)
{
System.out.println("IO exception in sendData");
}
}//sendData()
//method to read in network data
public void getData() throws IOException
{
try
{
networkmessage messageIn =(networkmessage)(ois.readObject());
System.out.println(messageIn.ipnum +" << "+messageIn.text);
}//try
catch (Exception exp1)
{
System.out.println("IO exception in sendData");
}
}//getData()
public void serverShutdown()
{
System.out.println("exiting initiated");
try
{
done = true;
textin = "Chat is terminated. Have a nice day.";
oos.close();
server.close();
connection.close();
}
catch (Exception One)
{
System.out.println("bad termination");
}
}
} // class serverProg

Thread server/client stops after 2nd client joins

I have a server which uses multiple threads to accept multiple clients. I have it at the moment that when a client types something, it appears on the server as Client: text This works fine for 1 client. However the problem is when a second client joins.
They join fine and they can type fine. But the first client can only type 1 more thing then they stop, i.e their messages doesn't appear on the server. I presume they can do 1 as the method has been started but doesn't repeat. I've tried a while (true) loop (as seen in the code) and recalling the method at the end, neither work. I'm new to programming so don't have much expertise in this. Please find the code below :) (Note, indention is correct, just hasn't copied across properly)
Server:
package dod;
import java.net.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.*;
public class Server implements Runnable
{
PrintWriter out;
BufferedReader in;
Socket clientSocket;
ServerSocket serverSocket;
int portNumber;
AtomicInteger numClients = new AtomicInteger(0);
public static void main(String[] args)
{
Server s = new Server();
s.startup();
}
public void run()
{}
/**
* Start the server on the user picked port
*/
public void startup()
{
try
{
System.out.println("Enter a port");
Scanner dif = new Scanner(System.in);
portNumber = Integer.parseInt(dif.nextLine());
dif.close();
serverSocket = new ServerSocket(portNumber);
newThread();
}
catch (IOException e) {
System.out.println("Error");
System.exit(0);
}
}
public void newThread()
{
Thread thread =new Thread("C"+numClients.getAndIncrement())
{
public void run()
{
accept();
}
};
thread.start();
}
public void accept()
{
try
{
clientSocket = serverSocket.accept();
System.out.println("A new client has just connected.");
} catch(IOException e)
{
System.out.println("error");
System.exit(0);
}
newThread();
listenCommand();
}
public void listenCommand()
{
while (true)
{
try
{
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String userInput;
while ((userInput = in.readLine()) != null)
{
System.out.println("client: " + userInput);
}
} catch (IOException e)
{
System.out.println("Error");
System.exit(0);
}
}
}
}
Client:
package dod;
import java.io.*;
import java.net.*;
public class Client
{
public static void main(String[] args) throws IOException {
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
try {
Socket serverSocket = new Socket(hostName, portNumber);
PrintWriter out = new PrintWriter(serverSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null)
{
out.println(userInput);
}
} catch(UnknownHostException e) {
System.out.println("error in host");
} catch(IOException e) {
System.out.println("error in IO");
}
}
}
Thank you! :)
*emphasized text*In the Server class you should have a Thread listening for new clients arriving and assigning them their own socket. You have the socket and the streams as a member variables, so everytime a new client comes you replace the socket. Also you open a new Thread for the accept connection, instead for the client itself.
Check the following (See that the client socket is another thread and I created a Runnable for it):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
public class Server
{
ServerSocket serverSocket;
int portNumber;
AtomicInteger numClients = new AtomicInteger(0);
public static void main(String[] args)
{
Server s = new Server();
s.startup();
}
/**
* Start the server on the user picked port
*/
public void startup()
{
try
{
System.out.println("Enter a port");
Scanner dif = new Scanner(System.in);
portNumber = Integer.parseInt(dif.nextLine());
dif.close();
serverSocket = new ServerSocket(portNumber);
newThread();
}
catch (IOException e) {
System.out.println("Error");
System.exit(0);
}
}
public void newThread()
{
Thread thread =new Thread("C"+numClients.getAndIncrement())
{
public void run()
{
while(true) {
try {
accept();
} catch (Exception e) {
// lof the exception
}
}
}
};
thread.start();
}
public void accept()
{
try
{
Socket clientSocket = serverSocket.accept();
new Thread(new ClientSocket(clientSocket)).start();
System.out.println("A new client has just connected.");
} catch(IOException e)
{
System.out.println("User disconnected");
System.exit(0);
}
}
class ClientSocket implements Runnable {
Socket clientSocket;
public ClientSocket(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
{
try
{
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String userInput;
while ((userInput = in.readLine()) != null)
{
System.out.println("client: " + userInput);
}
} catch (IOException e)
{
System.out.println("Error. Probably client disconnected");
// System.exit(0); do you want to exist when a client disconnects?
}
}
}
}
}

Categories