Skip to content

Instantly share code, notes, and snippets.

@fliedonion
Last active April 13, 2023 23:03
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save fliedonion/1002293af6fd043fbd6e729c13018562 to your computer and use it in GitHub Desktop.
Save fliedonion/1002293af6fd043fbd6e729c13018562 to your computer and use it in GitHub Desktop.

what is this

original source is http://www.instructables.com/id/Creating-a-Chat-Server-Using-Java/

I tested that code, but that doesnot work. I rewrite many part of that.

other

You can use your own lisk.

I feel weird about class named ServerThread is in client package (also ClientThread is in server package).

I'm not native English speaker. Correct my English welcome.

// place this file the path such ends with: ChatServer/server/ChatServer.java
package ChatServer.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ChatServer {
private static final int portNumber = 4444;
private int serverPort;
private List<ClientThread> clients; // or "protected static List<ClientThread> clients;"
public static void main(String[] args){
ChatServer server = new ChatServer(portNumber);
server.startServer();
}
public ChatServer(int portNumber){
this.serverPort = portNumber;
}
public List<ClientThread> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ClientThread>();
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(serverPort);
acceptClients(serverSocket);
} catch (IOException e){
System.err.println("Could not listen on port: "+serverPort);
System.exit(1);
}
}
private void acceptClients(ServerSocket serverSocket){
System.out.println("server starts port = " + serverSocket.getLocalSocketAddress());
while(true){
try{
Socket socket = serverSocket.accept();
System.out.println("accepts : " + socket.getRemoteSocketAddress());
ClientThread client = new ClientThread(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException ex){
System.out.println("Accept failed on : "+serverPort);
}
}
}
}
// place this file the path such ends with: ChatServer/client/Client.java
package ChatServer.client;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private static final String host = "localhost";
private static final int portNumber = 4444;
private String userName;
private String serverHost;
private int serverPort;
private Scanner userInputScanner;
public static void main(String[] args){
String readName = null;
Scanner scan = new Scanner(System.in);
System.out.println("Please input username:");
while(readName == null || readName.trim().equals("")){
// null, empty, whitespace(s) not allowed.
readName = scan.nextLine();
if(readName.trim().equals("")){
System.out.println("Invalid. Please enter again:");
}
}
Client client = new Client(readName, host, portNumber);
client.startClient(scan);
}
private Client(String userName, String host, int portNumber){
this.userName = userName;
this.serverHost = host;
this.serverPort = portNumber;
}
private void startClient(Scanner scan){
try{
Socket socket = new Socket(serverHost, serverPort);
Thread.sleep(1000); // waiting for network communicating.
ServerThread serverThread = new ServerThread(socket, userName);
Thread serverAccessThread = new Thread(serverThread);
serverAccessThread.start();
while(serverAccessThread.isAlive()){
if(scan.hasNextLine()){
serverThread.addNextMessage(scan.nextLine());
}
// NOTE: scan.hasNextLine waits input (in the other words block this thread's process).
// NOTE: If you use buffered reader or something else not waiting way,
// NOTE: I recommends write waiting short time like following.
// else {
// Thread.sleep(200);
// }
}
}catch(IOException ex){
System.err.println("Fatal Connection error!");
ex.printStackTrace();
}catch(InterruptedException ex){
System.out.println("Interrupted");
}
}
}
// place this file the path such ends with: ChatServer/server/ClientThread.java
package ChatServer.server;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class ClientThread implements Runnable {
private Socket socket;
private PrintWriter clientOut;
private ChatServer server;
public ClientThread(ChatServer server, Socket socket){
this.server = server;
this.socket = socket;
}
private PrintWriter getWriter(){
return clientOut;
}
@Override
public void run() {
try{
// setup
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
Scanner in = new Scanner(socket.getInputStream());
// start communicating
while(!socket.isClosed()){
if(in.hasNextLine()){
String input = in.nextLine();
// NOTE: if you want to check server can read input, uncomment next line and check server file console.
// System.out.println(input);
for(ClientThread thatClient : server.getClients()){
PrintWriter thatClientOut = thatClient.getWriter();
if(thatClientOut != null){
thatClientOut.write(input + "\r\n");
thatClientOut.flush();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// place this file the path such ends with: ChatServer/client/ServerThread.java
package ChatServer.client;
import java.io.*;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Scanner;
public class ServerThread implements Runnable {
private Socket socket;
private String userName;
private boolean isAlived;
private final LinkedList<String> messagesToSend;
private boolean hasMessages = false;
public ServerThread(Socket socket, String userName){
this.socket = socket;
this.userName = userName;
messagesToSend = new LinkedList<String>();
}
public void addNextMessage(String message){
synchronized (messagesToSend){
hasMessages = true;
messagesToSend.push(message);
}
}
@Override
public void run(){
System.out.println("Welcome :" + userName);
System.out.println("Local Port :" + socket.getLocalPort());
System.out.println("Server = " + socket.getRemoteSocketAddress() + ":" + socket.getPort());
try{
PrintWriter serverOut = new PrintWriter(socket.getOutputStream(), false);
InputStream serverInStream = socket.getInputStream();
Scanner serverIn = new Scanner(serverInStream);
// BufferedReader userBr = new BufferedReader(new InputStreamReader(userInStream));
// Scanner userIn = new Scanner(userInStream);
while(!socket.isClosed()){
if(serverInStream.available() > 0){
if(serverIn.hasNextLine()){
System.out.println(serverIn.nextLine());
}
}
if(hasMessages){
String nextSend = "";
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.println(userName + " > " + nextSend);
serverOut.flush();
}
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
}
@beerfekt
Copy link

beerfekt commented Nov 7, 2017

Well done! Now it works.
Thank you so much

@gavinconnolly9
Copy link

Hi, thanks for the great code!
Do you know how make a GUI that looks like the picture at the top of the http://www.instructables.com/id/Creating-a-Chat-Server-Using-Java/ page?
fssk8a1iljwgr24 medium

@filthfiend
Copy link

Hello!

I wrote a javafx im client/server based on your code.

Thank you for sharing this, it was really instructive.

I am new to github, I will give you credit on my project page as soon as I figure out how to do so.

https://github.com/dantahir/imClientAndServer

@Rahulk62
Copy link

Rahulk62 commented Apr 2, 2018

it is still not working
image

@Volpestyle
Copy link

Thank you so much, you saved my life! Your code is so organized and methodical. Much better than the original code.

@Omar-Handouk
Copy link

@Rahulk62 Compile the ClientThread First, it can't find the symbol because the ClientThread class is not found and the chatServer class uses ClientThread

@tnedzad
Copy link

tnedzad commented Feb 14, 2019

Field private Scanner userInputScanner; in Client class isn't used at all ?
and Field private boolean isAlive; in ServerThread class isn't used
am I wright ?

@clmbert6
Copy link

If you're using Eclipse, how do you get multiple clients to send messages to each other in this IDE?

@Douglas707
Copy link

how do you run it
mine wont work

@Douglas707
Copy link

What do i input for username?

@fliedonion
Copy link
Author

Sorry for procrastinate.

Some of the questions are about how to execute it, so let me explain.
I was also interested in the question of running it in Eclipse, so I tried it, even though I don't usually use Eclipse.
I only explain with Eclipse 2020.
Of course, you don't need to use Eclipse to run these programs.

note: This answer is a machine translation, so the sentence may be unnatural. I lightly checked the English text, though.

To run these programs, do like following:

  1. Run a server first.
    right click inside ChatServer.java source code
    right click inside ChatServer.java source code
    Choose Run > Java Application
    Choose Run > Java Application

  2. Then run a client.

Perform the same operation in Client.js.
スクリーンショット 2020-11-03 2 09 20
スクリーンショット 2020-11-03 2 09 27

You can see the runner pain like below:
note that: This is not current running list. This is a list of execution setting.
スクリーンショット 2020-11-03 2 13 31

  1. Switch the consoles to input and check output.

You can switch the console by clicking icon.
スクリーンショット 2020-11-03 2 14 07
スクリーンショット 2020-11-03 2 15 31

@diablo00a
Copy link

diablo00a commented Mar 23, 2021

dude can u tell me how i chage localhost to ip adress for use in lan chat pls

@jermsmcerms
Copy link

jermsmcerms commented Apr 9, 2021

I'm getting a null pointer access on the readName conditional in the Client class while(readName != null || readName.trim().isEmpty())

Edit: nevermind, I see that I wrote != instead of == for the lhs of the condition haha

@jermsmcerms
Copy link

There's issues with your scanners. The are not being closed and are causing leaks.

@lmhuong711
Copy link

Hello. I have compiled it with IntelliJ and I have successfully accepted from clients.

Here is in Server:
server starts port = 0.0.0.0/0.0.0.0:4444
accepts : /127.0.0.1:52503

Here is in Client:
Input username:
client1

But when im trying to send message, i tried to type in both client and server terminal, nothing happened. What should i do?

Here is in Server:
server starts port = 0.0.0.0/0.0.0.0:4444
accepts : /127.0.0.1:52503
hello

hi
wait?

client1

Here is in Client:
Input username:
client1
hello
send request
wahy

@werner-biela
Copy link

Just one question, How would you change this code to make it work with SSL to encrypt it?

@sltslt
Copy link

sltslt commented Apr 13, 2023

Thank you so much for sharing! This really helps me a lot on understanding concurrent programming and networking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment