java network programming TCP chat full duplex - java

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

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.

java server is receiving from 1 client only and not from the 2nd

Good day, I'm trying to create a Client/Server chat, that the 1st client send message to server and the server send it to client 2 and vice versa, but the server is just receiving from 1st client only and not from 2nd.
and also, how can i send messages from client 1 to 2 & vice versa
package s;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client
{
public static void main(String[] args) throws IOException, Throwable
{
Socket s;
BufferedReader in;
PrintWriter out;
Scanner sc = new Scanner(System.in);
s = new Socket(InetAddress.getLocalHost(),9000);
System.out.println("Connection pending");
in = new BufferedReader (new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream());
String msg = in.readLine();
System.out.println(msg);
while(msg!="")
{
msg = sc.nextLine();
out.println(msg+"\n");
out.flush();
}
s.close();
sc.close();
}
}
=============================================
package s;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class TClient extends Thread
{
private int num;
private Socket s;
private BufferedReader in;
private PrintWriter out;
public Socket getS()
{
return s;
}
public BufferedReader getIn()
{
return in;
}
public PrintWriter getOut()
{
return out;
}
public TClient(Socket s,int num) throws IOException
{
this.s = s;
this.setNum(num);
System.out.println("Client"+num);
out = new PrintWriter(s.getOutputStream());
in = new BufferedReader (new InputStreamReader(s.getInputStream()));
out.println("Connected"+num+"\n");
out.flush();
}
public void run()
{
while(true)
{
try
{
String msg="";
msg = in.readLine();
System.out.println(msg);
if (msg.equals(".")) break;
}
catch (IOException e)
{
}
}
try
{
s.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
}
========================================================
package s;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
public static void main(String[] args)
{
ServerSocket ss ;
Socket s = null ;
int nb_clients = 0;
String msg = "";
TClient[] connexions = new TClient[2];
try
{
ss = new ServerSocket(9000);
System.out.println("Server is listening in:"+ss.getLocalPort());
boolean continu = false;
while(!continu)
{
s = ss.accept();
connexions[nb_clients] = new TClient(s,nb_clients+1);
connexions[nb_clients].start();
nb_clients++;
if (nb_clients>=2) continu=true;
}
System.out.println("Clients connected");
s.close();
ss.close();
}
catch(IOException e)
{
}
}
}
========================================
and the output of each terminal is :
Server is listening in:9000
Client1
Client2
Clients connected
and the output of the 2 clients are :
Connection pending
Connected1
Connection pending
Connected2
if i write a message from 1 & 2 to the server, the server output will be like this:
Server is listening in:9000
Client1
Client2
Clients connected
111111111111111111111111111111111111
================================================================
UPDATE :
i changed a condition in server
if (nb_clients>2) continu=true;
and now i can recieve from both clients, now i have to know how i make them communicate between the clients
Solution for two clients.
Sending messages from one client to another client.
The server will have to marshall the messages between the clients.
public class Server
{
static TClient[] connexions = new TClient[2];
public static void send(int clientNum, String message) {
TClient t = connexions[clientNum];
if(t != null) {
t.getOut().println(message);
t.getOut().flush();
}
}
}
In TClient added:
public void sendMessage(String message) {
int client = (getNum()-1)==1 ? 0:1;
Server.send(client, message);
System.out.printf("Sending message(%s) to client:%d from client:%d%n",message,client,getNum());
}
which I added a call to inside your while loop.
In Client I used another thread for receiving message from the server called ReceiveMessageThread:
public class Client
{
public static void main(String[] args) throws IOException, Throwable
{
Socket s;
BufferedReader in;
PrintWriter out;
Scanner sc = new Scanner(System.in);
s = new Socket(InetAddress.getLocalHost(), 9000);
System.out.println("Connection pending");
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream());
ReceiveMessageThread thread = new ReceiveMessageThread(in);
String msg = in.readLine();
System.out.println(msg);
thread.start();
while (msg != "")
{
msg = sc.nextLine();
out.println(msg + "\n");
out.flush();
}
s.close();
sc.close();
}
public static class ReceiveMessageThread extends Thread
{
private BufferedReader in;
public ReceiveMessageThread(BufferedReader in)
{
this.in = in;
}
public void run()
{
while (true)
{
try
{
String message = readMessage(in);
if (message != null && !message.equals(""))
System.out.println(message);
} catch (IOException ie)
{
ie.printStackTrace();
}
}
}
public String readMessage(BufferedReader in) throws IOException
{
String msgreceived = "";
String readValue = "";
while (in.ready())
{
readValue = in.readLine();
if (readValue != null)
msgreceived += readValue;
}
return msgreceived;
}
}
}
in server i changed :
if (nb_clients>2) continu=true;
and the server reads from different clients.

How do I reconnect a client when server is down in 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
}

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