Java Server with Multiclient communication.
Here I am sharing you a nice Chat Program having one server that is communicating with multiple clients using TCP protocol as per your requirement.
Program contains:
- Each client is informed wherever a new client is added along with their name and position.
- It also checks for existing names. Program doesn't allow multiple clients using same name.
Use this program as initial starter for your game. Please let me know if you want to add new functionality in the program.
Here is the code (see code comments for more clarification):
Note: replace host name in LiveChatClient.java file before running this program at port no 1234
Steps to run the program:
- first run LiveChatServer only for single time
- then run LiveChatClient for multiple clients as many as you want to add
Opcode.java:
Operation code that is used to set a client-server communication protocol
package com.chat;
/**************** an interface to define different operation code **************/
public interface Opcode {
int CLIENT_CONNECTEING = 1;
int CLIENT_CONNECTED = 2;
}
LiveChatServer.java:
Single server that is controlling multiple clients
package com.chat;
/************************ Live Chat Server *******************/
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class LiveChatServer {
// Connection state info
private static LinkedHashMap<String, ClientThread> clientInfo = new LinkedHashMap<String, ClientThread>();
// TCP Components
private ServerSocket serverSocket;
// Main Constructor
public LiveChatServer() {
startServer();// start the server
}
public void startServer() {
String port = "1234";
try {
// in constractor we are passing port no, back log and bind address whick will be local
// host
// port no - the specified port, or 0 to use any free port.
// backlog - the maximum length of the queue. use default if it is equal or less than 0
// bindAddr - the local InetAddress the server will bind to
int portNo = Integer.valueOf(port);
serverSocket = new ServerSocket(portNo, 0, InetAddress.getLocalHost());
System.out.println(serverSocket);
System.out.println(serverSocket.getInetAddress().getHostName() + ":"
+ serverSocket.getLocalPort());
while (true) {
Socket socket = serverSocket.accept();
new ClientThread(socket);
}
} catch (IOException e) {
System.out.println("IO Exception:" + e);
System.exit(1);
} catch (NumberFormatException e) {
System.out.println("Number Format Exception:" + e);
System.exit(1);
}
}
public static HashMap<String, ClientThread> getClientInfo() {
return clientInfo;
}
// *********************************** Main Method ********************
public static void main(String args[]) {
new LiveChatServer();
}
}
LiveChatClient.java:
Multiple clients talking to each other via server
package com.chat;
/************************ Live Chat Client *******************/
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.net.SocketException;
public class LiveChatClient {
private String chatName;// current user's chat name(max 7 char if greater than show as 6
// char+...
private String serverAddress;
// TCP Components
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public LiveChatClient() {
initHostName();
runClient();// have fun
}
public void initHostName() {
try {
//replace host name with your computer name or IP address
serverAddress = "[hostname]";
if (serverAddress == null)
System.exit(1);
serverAddress = serverAddress.trim();
if (serverAddress.length() == 0)// empty field
{
System.out.println("Server IP Address or Name can't be blank.");
initHostName();
return;
}
System.out.println("Trying to connect with server...\nServer IP Address:"
+ serverAddress);
// create socket
InetAddress inetAddress = InetAddress.getByName(serverAddress);
if (!inetAddress.isReachable(60000))// 60 sec
{
System.out
.println("Error! Unable to connect with server.\nServer IP Address may be wrong.");
System.exit(1);
}
initPortNo();
} catch (SocketException e) {
System.out.println("Socket Exception:\n" + e);
initHostName();
return;
} catch (IOException e) {
initHostName();
return;
}
}
public void initPortNo() {
try {
String portNo = "1234";
portNo = portNo.trim();
if (portNo.length() == 0)// empty field
{
System.out.println("Server port No can't be blank.");
initPortNo();
return;
}
System.out.println("Trying to connect with server...\nServer Port No:" + portNo);
socket = new Socket(serverAddress, 1234);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException e) {
System.out.println("IO Exception:\n" + e);
initPortNo();
return;
}
}
public void sendChatName() throws IOException {
System.out.println("Enter your name:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if (name == null)
System.exit(1);
// title case (get only first 9 chars of chat name)
name = name.trim();
if (name.equalsIgnoreCase("All")) {
System.out.println("This name is already reserved. Try different one.");
sendChatName();
return;
}
if (name.length() == 0) {
System.out.println("Please enter your chat name.");
sendChatName();
return;
}
if (name.length() == 1)
chatName = String.valueOf(name.charAt(0)).toUpperCase();
if (name.length() > 1 && name.length() < 10)
chatName = String.valueOf(name.charAt(0)).toUpperCase()
+ name.substring(1).toLowerCase();
else if (name.length() > 9)
chatName = String.valueOf(name.charAt(0)).toUpperCase()
+ name.substring(1, 10).toLowerCase();
// sending opcode first then sending chatName to the server
out.println(Opcode.CLIENT_CONNECTEING);
out.println(chatName);
}
public void runClient() {
try {
sendChatName();
while (true) {
int opcode = Integer.parseInt(in.readLine());
switch (opcode) {
case Opcode.CLIENT_CONNECTEING:
// this client is connecting
boolean result = Boolean.valueOf(in.readLine());
if (result) {
System.out
.println(chatName + " is already present. Try different one.");
runClient();
}
break;
case Opcode.CLIENT_CONNECTED:
// a new client is connected
Integer totalClient = Integer.valueOf(in.readLine());
System.out.println("Total Client:" + totalClient);
for (int i = 0; i < totalClient; i++) {
String client = in.readLine();
System.out.println((i + 1) + ":" + client);
}
break;
}
}
} catch (IOException e) {
System.out.println("Client is closed...");
}
}
// *********************************** Main Method ********************
public static void main(String args[]) {
new LiveChatClient();
}
}
ClientThread.java:
Multiple thread started by server one for each client and containing information about all connected clients
package com.chat;
/************************ Client Thread *******************/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
public class ClientThread implements Runnable {
// TCP Components
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String chatName;
// seperate thread
private Thread thread;
// boolean variable to check that client is running or not
private volatile boolean isRunning = true;
// opcode
private int opcode;
private HashMap<String, ClientThread> clientInfo = new HashMap<String, ClientThread>();
public ClientThread(Socket socket) {
try {
this.socket = socket;
this.clientInfo = LiveChatServer.getClientInfo();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
thread = new Thread(this);
thread.start();
} catch (IOException e) {
System.out.println(e);
}
}
public void run() {
try {
while (isRunning) {
if (!in.ready())
continue;
opcode = Integer.parseInt(in.readLine());// getting opcode first from client
switch (opcode) {
case Opcode.CLIENT_CONNECTEING:
chatName = in.readLine();
boolean result = clientInfo.containsKey(chatName);
out.println(Opcode.CLIENT_CONNECTEING);
out.println(result);
if (result)// wait for another chat name if already present
continue;
// send list of already online users to new online user
// for (Object user : clientInfo.keySet().toArray()) {
// out.println(Opcode.CLIENT_CONNECTED);
// out.println(user.toString());
// }
// put new entry in clientInfo hashmap
clientInfo.put(chatName, this);
int i = 0;
for (String key : clientInfo.keySet()) {
if (key.equals(chatName)) {
System.out.println(chatName + " added at " + (i + 1) + " position");
}
i++;
}
// tell other users about new added user and update their online users list
for (ClientThread client : clientInfo.values()) {
client.out.println(Opcode.CLIENT_CONNECTED);
client.out.println(clientInfo.size());
for (ClientThread client1 : clientInfo.values()) {
client.out.println(client1.chatName);
}
}
break;
}
}
// clsoe all connections
out.close();
in.close();
socket.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
Here is the output when two client are added.
Server:
ServerSocket[addr=computerName/IPAddress,port=0,localport=1234]
computerName:1234
Abc added at 1 position
Xyz added at 2 position
Client 1:
Trying to connect with server...
Server IP Address:computerName
Trying to connect with server...
Server Port No:1234
Enter your name:
abc
Total Client:1
1:Abc
Total Client:2
1:Abc
2:Xyz
Client 2:
Trying to connect with server...
Server IP Address:computerName
Trying to connect with server...
Server Port No:1234
Enter your name:
xyz
Total Client:2
1:Abc
2:Xyz
Have 2 threads, one for user 1, and one for user 2. They should communicate to each other using a shared object and notify each other when events occur. Spawn thread 1 when first user connects and spawn thread 2 when second user connects.