Java socket example chat

How to Create a Chat Console Application in Java using Socket

In this Java network programming tutorial, you will learn how to create a chat application in Java using Socket programming. Source code is provided for you to download.

1. Overview of the Java Chat Application

The Java Chat application you are going to build is a console application that is launched from the command line. The server and clients can run on different computers in the same network, e.g. Local Area Network (LAN).

There can be multiple clients connect to a server and they can chat to each other, just like in a chat room where everyone can see other users’ messages. There’s no private chat between two users, for simplicity.

After getting connected to the server, a user must provide his or her name to enter the chat. The server sends a list of currently online users to the new user.

Every user is notified when a new user arrives and when a user has gone. Each message is prefixed with the username to keep track who sent the message.

And finally, the user says ‘bye’ to quit the chat.

The application consists of two parts: server and client. Each part can run independently on separate computers.

Читайте также:  Php require with get

Now, let’s see how to code this Java chat application in details.

2. Create the Chat Server Program

The ChatServer class starts the server, listening on a specific port. When a new client gets connected, an instance of UserThread is created to serve that client. Since each connection is processed in a separate thread, the server is able to handle multiple clients at the same time.

The following is source code of the ChatServer class:

package net.codejava.networking.chat.server; import java.io.*; import java.net.*; import java.util.*; /** * This is the chat server program. * Press Ctrl + C to terminate the program. * * @author www.codejava.net */ public class ChatServer < private int port; private SetuserNames = new HashSet<>(); private Set userThreads = new HashSet<>(); public ChatServer(int port) < this.port = port; >public void execute() < try (ServerSocket serverSocket = new ServerSocket(port)) < System.out.println("Chat Server is listening on port " + port); while (true) < Socket socket = serverSocket.accept(); System.out.println("New user connected"); UserThread newUser = new UserThread(socket, this); userThreads.add(newUser); newUser.start(); >> catch (IOException ex) < System.out.println("Error in the server: " + ex.getMessage()); ex.printStackTrace(); >> public static void main(String[] args) < if (args.length < 1) < System.out.println("Syntax: java ChatServer "); System.exit(0); > int port = Integer.parseInt(args[0]); ChatServer server = new ChatServer(port); server.execute(); > /** * Delivers a message from one user to others (broadcasting) */ void broadcast(String message, UserThread excludeUser) < for (UserThread aUser : userThreads) < if (aUser != excludeUser) < aUser.sendMessage(message); >> > /** * Stores username of the newly connected client. */ void addUserName(String userName) < userNames.add(userName); >/** * When a client is disconneted, removes the associated username and UserThread */ void removeUser(String userName, UserThread aUser) < boolean removed = userNames.remove(userName); if (removed) < userThreads.remove(aUser); System.out.println("The user " + userName + " quitted"); >> Set getUserNames() < return this.userNames; >/** * Returns true if there are other users connected (not count the currently connected user) */ boolean hasUsers() < return !this.userNames.isEmpty(); >>

As you can see, the ChatServer class has two Set collections to keep track the names and threads of the connected clients. Set is used because it doesn’t allow duplication and the order of elements does not matter:

private Set userNames = new HashSet<>(); private Set userThreads = new HashSet<>();

An important method in the ChatServer class is broadcast() which deliver a message from one client to all others clients:

void broadcast(String message, UserThread excludeUser) < for (UserThread aUser : userThreads) < if (aUser != excludeUser) < aUser.sendMessage(message); >> >

The UserThread class is responsible for reading messages sent from the client and broadcasting messages to all other clients. First, it sends a list of online users to the new user. Then it reads the username and notifies other users about the new user.

The following code is of the UserThread class:

package net.codejava.networking.chat.server; import java.io.*; import java.net.*; import java.util.*; /** * This thread handles connection for each connected client, so the server * can handle multiple clients at the same time. * * @author www.codejava.net */ public class UserThread extends Thread < private Socket socket; private ChatServer server; private PrintWriter writer; public UserThread(Socket socket, ChatServer server) < this.socket = socket; this.server = server; >public void run() < try < InputStream input = socket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); OutputStream output = socket.getOutputStream(); writer = new PrintWriter(output, true); printUsers(); String userName = reader.readLine(); server.addUserName(userName); String serverMessage = "New user connected: " + userName; server.broadcast(serverMessage, this); String clientMessage; do < clientMessage = reader.readLine(); serverMessage = "[" + userName + "]: " + clientMessage; server.broadcast(serverMessage, this); >while (!clientMessage.equals("bye")); server.removeUser(userName, this); socket.close(); serverMessage = userName + " has quitted."; server.broadcast(serverMessage, this); > catch (IOException ex) < System.out.println("Error in UserThread: " + ex.getMessage()); ex.printStackTrace(); >> /** * Sends a list of online users to the newly connected user. */ void printUsers() < if (server.hasUsers()) < writer.println("Connected users: " + server.getUserNames()); >else < writer.println("No other users connected"); >> /** * Sends a message to the client. */ void sendMessage(String message) < writer.println(message); >>

Then it enters a loop of reading message from the user and sending it to all other users, until the user sends ‘bye’ indicating he or she is going to quit. And finally it notifies other users about the disconnection of this user and closes the connection.

3. Create the Chat Client Program

The ChatClient starts the client program, connects to a server specified by hostname/IP address and port number. Once the connection is made, it creates and starts two threads ReadThread and WriteThread .

Here is source code of the ChatClient class:

package net.codejava.networking.chat.client; import java.net.*; import java.io.*; /** * This is the chat client program. * Type 'bye' to terminte the program. * * @author www.codejava.net */ public class ChatClient < private String hostname; private int port; private String userName; public ChatClient(String hostname, int port) < this.hostname = hostname; this.port = port; >public void execute() < try < Socket socket = new Socket(hostname, port); System.out.println("Connected to the chat server"); new ReadThread(socket, this).start(); new WriteThread(socket, this).start(); >catch (UnknownHostException ex) < System.out.println("Server not found: " + ex.getMessage()); >catch (IOException ex) < System.out.println("I/O Error: " + ex.getMessage()); >> void setUserName(String userName) < this.userName = userName; >String getUserName() < return this.userName; >public static void main(String[] args) < if (args.length < 2) return; String hostname = args[0]; int port = Integer.parseInt(args[1]); ChatClient client = new ChatClient(hostname, port); client.execute(); >>

The ReadThread is responsible for reading input from the server and printing it to the console repeatedly, until the client disconnects. This class is implemented as follows:

package net.codejava.networking.chat.client; import java.io.*; import java.net.*; /** * This thread is responsible for reading server's input and printing it * to the console. * It runs in an infinite loop until the client disconnects from the server. * * @author www.codejava.net */ public class ReadThread extends Thread < private BufferedReader reader; private Socket socket; private ChatClient client; public ReadThread(Socket socket, ChatClient client) < this.socket = socket; this.client = client; try < InputStream input = socket.getInputStream(); reader = new BufferedReader(new InputStreamReader(input)); >catch (IOException ex) < System.out.println("Error getting input stream: " + ex.getMessage()); ex.printStackTrace(); >> public void run() < while (true) < try < String response = reader.readLine(); System.out.println("\n" + response); // prints the username after displaying the server's message if (client.getUserName() != null) < System.out.print("[" + client.getUserName() + "]: "); >> catch (IOException ex) < System.out.println("Error reading from server: " + ex.getMessage()); ex.printStackTrace(); break; >> > >

And the WriteThread is responsible for reading input from the user and sending it to the server, continuously until the user types ‘bye’ to end the chat. This class is implemented as follows:

package net.codejava.networking.chat.client; import java.io.*; import java.net.*; /** * This thread is responsible for reading user's input and send it * to the server. * It runs in an infinite loop until the user types 'bye' to quit. * * @author www.codejava.net */ public class WriteThread extends Thread < private PrintWriter writer; private Socket socket; private ChatClient client; public WriteThread(Socket socket, ChatClient client) < this.socket = socket; this.client = client; try < OutputStream output = socket.getOutputStream(); writer = new PrintWriter(output, true); >catch (IOException ex) < System.out.println("Error getting output stream: " + ex.getMessage()); ex.printStackTrace(); >> public void run() < Console console = System.console(); String userName = console.readLine("\nEnter your name: "); client.setUserName(userName); writer.println(userName); String text; do < text = console.readLine("[" + userName + "]: "); writer.println(text); >while (!text.equals("bye")); try < socket.close(); >catch (IOException ex) < System.out.println("Error writing to server: " + ex.getMessage()); >> >

The reasons for running these two threads simultaneously is that the reading operation always blocks the current thread (both reading user’s input from command line and reading server’s input via network). That means if the current thread is waiting for the user’s input, it can’t read input from the server.

Therefore, two separate threads are used to make the client responsive: it can display messages from other users while reading message from the current user.

That’s how the chat application is designed. For more details, you can read the comments in the source code provided. But there are no many comments because the code is self-explanatory.

4. How to Run the Chat Server

You need to specify the port number when running the server program from the command line. For example:

This starts the server listening on the port number 8989, and you see the following output in the server once it started:

Chat Server is listening on port 8989

5. How to Run a Chat Client

To run the client, you need to specify the server’s hostname/IP address and port number in the command line. For example:

java ChatClient localhost 8989

This tells the client to connect to the server at localhost on port 8989. Then you see the following message in the server’s console:

Connected to chat server No other users connected

You see, the server tells the client how many users are connected, but there’s no user at this time. Then the program asks for the username:

Enter your name: John [John]:_

Now, let’s start the second client with username is Peter. At this time, you see the server tells that there’s one online user is John:

Type some messages from John and Peter and you see each user sees other’s messages, just like talking in a chat room.

Now, John wants to quit so he types ‘bye’- the client program terminates, and you see the following output in the server’s console:

That’s basically how the chat application is running. You can test it with more clients and the application is still running smoothly. The following screenshot illustrates a test with 4 clients:

Chat Console Application Testing

Now, it’s your time to play around with this chat application with the source code attached.

Other Java network tutorials:

About the Author:

Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.

Add comment

Comments

The code doesn’t run. It’s main class cant be found. Moreso, this code doesn’t use Scanner(system.in) so how will the user be able to chat via the console?

I can not run the Chat Client; I have no idea how to specify the server’s hostname/IP address and port number. Can someone please help me?

Источник

Чат на Java (Серверная часть)

Чат на Java (Серверная часть)

Всем доброго времени суток. На связи Алексей Гулынин. В данной статье я бы хотел написать серверную часть простого чата на Java. Все комментарии будут даны в коде.

Скачать уже готовый проект полностью можно по ссылке.

Проект серверной части будет состоять из 3 файлов:

  • Server.java — класс, который описывает логику работы сервера.
  • ClientHandler.java — класс, в котором обрабатывается подключение клиента к серверу.
  • Main.java .

В классе Main будет просто создаваться экземпляр нашего сервера:

package server; public class Main < public static void main(String[] args) < Server server = new Server(); >>
package server; import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class Server < // порт, который будет прослушивать наш сервер static final int PORT = 3443; // список клиентов, которые будут подключаться к серверу private ArrayListclients = new ArrayList(); public Server() < // сокет клиента, это некий поток, который будет подключаться к серверу // по адресу и порту Socket clientSocket = null; // серверный сокет ServerSocket serverSocket = null; try < // создаём серверный сокет на определенном порту serverSocket = new ServerSocket(PORT); System.out.println("Сервер запущен!"); // запускаем бесконечный цикл while (true) < // таким образом ждём подключений от сервера clientSocket = serverSocket.accept(); // создаём обработчик клиента, который подключился к серверу // this - это наш сервер ClientHandler client = new ClientHandler(clientSocket, this); clients.add(client); // каждое подключение клиента обрабатываем в новом потоке new Thread(client).start(); >> catch (IOException ex) < ex.printStackTrace(); >finally < try < // закрываем подключение clientSocket.close(); System.out.println("Сервер остановлен"); serverSocket.close(); >catch (IOException ex) < ex.printStackTrace(); >> > // отправляем сообщение всем клиентам public void sendMessageToAllClients(String msg) < for (ClientHandler o : clients) < o.sendMsg(msg); >> // удаляем клиента из коллекции при выходе из чата public void removeClient(ClientHandler client) < clients.remove(client); >>
package server; import java.io.IOException; import java.io.PrintWriter; import java.net.Socket; import java.util.ArrayList; import java.util.Scanner; // реализуем интерфейс Runnable, который позволяет работать с потоками public class ClientHandler implements Runnable < // экземпляр нашего сервера private Server server; // исходящее сообщение private PrintWriter outMessage; // входящее собщение private Scanner inMessage; private static final String HOST = "localhost"; private static final int PORT = 3443; // клиентский сокет private Socket clientSocket = null; // количество клиента в чате, статичное поле private static int clients_count = 0; // конструктор, который принимает клиентский сокет и сервер public ClientHandler(Socket socket, Server server) < try < clients_count++; this.server = server; this.clientSocket = socket; this.outMessage = new PrintWriter(socket.getOutputStream()); this.inMessage = new Scanner(socket.getInputStream()); >catch (IOException ex) < ex.printStackTrace(); >> // Переопределяем метод run(), который вызывается когда // мы вызываем new Thread(client).start(); @Override public void run() < try < while (true) < // сервер отправляет сообщение server.sendMessageToAllClients("Новый участник вошёл в чат!"); server.sendMessageToAllClients("Клиентов в чате = " + clients_count); break; >while (true) < // Если от клиента пришло сообщение if (inMessage.hasNext()) < String clientMessage = inMessage.nextLine(); // если клиент отправляет данное сообщение, то цикл прерывается и // клиент выходит из чата if (clientMessage.equalsIgnoreCase("##session##end##")) < break; >// выводим в консоль сообщение (для теста) System.out.println(clientMessage); // отправляем данное сообщение всем клиентам server.sendMessageToAllClients(clientMessage); > // останавливаем выполнение потока на 100 мс Thread.sleep(100); > > catch (InterruptedException ex) < ex.printStackTrace(); >finally < this.close(); >> // отправляем сообщение public void sendMsg(String msg) < try < outMessage.println(msg); outMessage.flush(); >catch (Exception ex) < ex.printStackTrace(); >> // клиент выходит из чата public void close() < // удаляем клиента из списка server.removeClient(this); clients_count--; server.sendMessageToAllClients("Клиентов в чате = " + clients_count); >>

В данной статье мы создали серверную часть простого чата на Java.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.

Источник

Оцените статью