Compare commits
10 Commits
11a00f6959
...
handshake
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d3bca136a | ||
|
|
a041193ce2 | ||
|
|
5986b2f43c | ||
|
|
aaf2e83b35 | ||
|
|
8f46e8dc91 | ||
|
|
e40d9ac8b8 | ||
|
|
09637ba775 | ||
|
|
f0a9617649 | ||
|
|
ac631cbe0f | ||
|
|
3554e42718 |
@@ -1,18 +1,39 @@
|
|||||||
## Getting Started
|
# ChatAPP
|
||||||
|
An instant messaging app using Java and the UDP protocol.
|
||||||
|
|
||||||
Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code.
|
## How to run
|
||||||
|
|
||||||
## Folder Structure
|
> [!WARNING]
|
||||||
|
> As of now, the app rely on ANSI escape character, thus not available on Windows.
|
||||||
|
> However, this feature is under development.
|
||||||
|
|
||||||
The workspace contains two folders by default, where:
|
You can run the app by launching the `ChatApp` class. This will create the server (port `6665`) and a first client,
|
||||||
|
(creating by the way a room (`101`)).
|
||||||
|
|
||||||
- `src`: the folder to maintain sources
|
You can then create more clients by launching the `Client` class. It will connect to the server
|
||||||
- `lib`: the folder to maintain dependencies
|
(be sure you launched it first) on the default port `6665`.
|
||||||
|
|
||||||
Meanwhile, the compiled output files will be generated in the `bin` folder by default.
|
## How to use
|
||||||
|
As soon as you launch a client, you will be prompted to enter your name. You will then be in the lobby. From here you
|
||||||
|
can join whatever room that is created, and you will be able to chat with the other clients in the room.
|
||||||
|
You will also be able to create a new room.
|
||||||
|
|
||||||
> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there.
|
## Commands
|
||||||
|
> [!TIP]
|
||||||
|
> The commands can be found by typing `/help` in the chat, in the lobby or in any room.
|
||||||
|
|
||||||
## Dependency Management
|
> [!NOTE]
|
||||||
|
> All the commands are prefixed by `/`.
|
||||||
|
|
||||||
The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies).
|
- /createRoom *roomName*
|
||||||
|
- /listRooms
|
||||||
|
- /joinRoom *roomName*
|
||||||
|
- /leaveRoom
|
||||||
|
- /help
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> There are some aliases for the commands:
|
||||||
|
> - /create
|
||||||
|
> - /list
|
||||||
|
> - /join
|
||||||
|
> - /leave
|
||||||
@@ -6,16 +6,18 @@ import server.Server;
|
|||||||
|
|
||||||
public class ChatApp {
|
public class ChatApp {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
Server server = new Server(6665);
|
int port = 6665;
|
||||||
Client client = new Client(new InetSocketAddress("localhost", 6665));
|
Server server = new Server(port);
|
||||||
|
Client client = new Client(new InetSocketAddress("localhost", port));
|
||||||
|
|
||||||
client.SendCreateRoom("Room1");
|
client.SendCreateRoom("101");
|
||||||
client.RequestRoomList();
|
|
||||||
client.SendChatMessage("Hello");
|
|
||||||
|
|
||||||
Scanner scanner = new Scanner(System.in);
|
Scanner scanner = new Scanner(System.in);
|
||||||
while (true) {
|
while (true) {
|
||||||
String message = scanner.nextLine();
|
String message = scanner.nextLine();
|
||||||
|
System.out.print("\033[1A");
|
||||||
|
System.out.print("\r\033[2K");
|
||||||
|
System.out.flush();
|
||||||
client.visitMessage(message);
|
client.visitMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.net.SocketException;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import network.protocol.ANSIColor;
|
||||||
import network.protocol.packets.*;
|
import network.protocol.packets.*;
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
@@ -14,8 +15,10 @@ public class Client {
|
|||||||
private final ClientConnexion connexion;
|
private final ClientConnexion connexion;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
String host = "localhost";
|
||||||
|
int port = 6665;
|
||||||
try {
|
try {
|
||||||
Client client = new Client(new InetSocketAddress("localhost", 6665));
|
Client client = new Client(new InetSocketAddress(host, port));
|
||||||
Scanner scanner = new Scanner(System.in);
|
Scanner scanner = new Scanner(System.in);
|
||||||
while(true) {
|
while(true) {
|
||||||
String message = scanner.nextLine();
|
String message = scanner.nextLine();
|
||||||
@@ -28,7 +31,27 @@ public class Client {
|
|||||||
|
|
||||||
public Client(InetSocketAddress serverAddress) throws SocketException {
|
public Client(InetSocketAddress serverAddress) throws SocketException {
|
||||||
this.connexion = new ClientConnexion(new DatagramSocket(), serverAddress);
|
this.connexion = new ClientConnexion(new DatagramSocket(), serverAddress);
|
||||||
login("Moi");
|
int tries = 0;
|
||||||
|
try {
|
||||||
|
connexion.sendPacket(new HandshakePacket());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
while(!connexion.connected) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
if(tries++ > 5) {
|
||||||
|
System.out.println("Server is not responding");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Scanner scanner = new Scanner(System.in);
|
||||||
|
System.out.println("Enter your pseudo:");
|
||||||
|
String pseudo = scanner.nextLine();
|
||||||
|
login(pseudo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitMessage(String message){
|
public void visitMessage(String message){
|
||||||
@@ -37,15 +60,29 @@ public class Client {
|
|||||||
if(message.startsWith("/createRoom ")) {
|
if(message.startsWith("/createRoom ")) {
|
||||||
String roomName = message.substring(12).trim();
|
String roomName = message.substring(12).trim();
|
||||||
SendCreateRoom(roomName);
|
SendCreateRoom(roomName);
|
||||||
} else if(message.startsWith("/listRooms")) {
|
} else if(message.startsWith("/create ")){
|
||||||
|
String roomName = message.substring(8).trim();
|
||||||
|
SendCreateRoom(roomName);
|
||||||
|
} else if(message.equals("/listRooms") || message.equals("/list")) {
|
||||||
RequestRoomList();
|
RequestRoomList();
|
||||||
} else if(message.startsWith("/joinRoom ")) {
|
} else if(message.startsWith("/joinRoom ")) {
|
||||||
String roomName = message.substring(10).trim();
|
String roomName = message.substring(10).trim();
|
||||||
SendJoinRoom(roomName);
|
SendJoinRoom(roomName);
|
||||||
} else if(message.startsWith("/leaveRoom")) {
|
} else if(message.startsWith("/join ")){
|
||||||
|
String roomName = message.substring(6).trim();
|
||||||
|
SendJoinRoom(roomName);
|
||||||
|
} else if(message.equals("/leaveRoom") || message.equals("/leave")) {
|
||||||
SendLeaveRoom();
|
SendLeaveRoom();
|
||||||
} else {
|
} else if(message.equals("/help")) {
|
||||||
System.out.println("Unknown command");
|
System.out.println("Available commands:");
|
||||||
|
System.out.println("\t/createRoom <roomName>");
|
||||||
|
System.out.println("\t/listRooms");
|
||||||
|
System.out.println("\t/joinRoom <roomName>");
|
||||||
|
System.out.println("\t/leaveRoom");
|
||||||
|
System.out.println("\t/help");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println(ANSIColor.formatString("&rUnknown command&n"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SendChatMessage(message);
|
SendChatMessage(message);
|
||||||
|
|||||||
@@ -7,23 +7,17 @@ import java.net.InetSocketAddress;
|
|||||||
import network.PacketHandler;
|
import network.PacketHandler;
|
||||||
import network.SocketReader;
|
import network.SocketReader;
|
||||||
import network.SocketWriter;
|
import network.SocketWriter;
|
||||||
|
import network.protocol.ANSIColor;
|
||||||
import network.protocol.Packet;
|
import network.protocol.Packet;
|
||||||
import network.protocol.PacketVisitor;
|
import network.protocol.PacketVisitor;
|
||||||
import network.protocol.packets.ChatMessagePacket;
|
import network.protocol.packets.*;
|
||||||
import network.protocol.packets.CreateRoomPacket;
|
|
||||||
import network.protocol.packets.JoinRoomPacket;
|
|
||||||
import network.protocol.packets.LeaveRoomPacket;
|
|
||||||
import network.protocol.packets.LoginPacket;
|
|
||||||
import network.protocol.packets.RequestRoomListPacket;
|
|
||||||
import network.protocol.packets.RoomListPacket;
|
|
||||||
import network.protocol.packets.SendChatMessagePacket;
|
|
||||||
import network.protocol.packets.ServerResponsePacket;
|
|
||||||
|
|
||||||
public class ClientConnexion implements PacketVisitor, PacketHandler{
|
public class ClientConnexion implements PacketVisitor, PacketHandler{
|
||||||
|
|
||||||
private final InetSocketAddress serverAddress;
|
private final InetSocketAddress serverAddress;
|
||||||
private final SocketWriter writer;
|
private final SocketWriter writer;
|
||||||
private final SocketReader reader;
|
private final SocketReader reader;
|
||||||
|
protected boolean connected = false;
|
||||||
|
|
||||||
public ClientConnexion(DatagramSocket socket, InetSocketAddress serverAddress) {
|
public ClientConnexion(DatagramSocket socket, InetSocketAddress serverAddress) {
|
||||||
this.serverAddress = serverAddress;
|
this.serverAddress = serverAddress;
|
||||||
@@ -49,12 +43,14 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{
|
|||||||
public void visitPacket(ChatMessagePacket packet) {
|
public void visitPacket(ChatMessagePacket packet) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String time = packet.getTime().toString();
|
String time = packet.getTime().toString();
|
||||||
sb.append(time, 11, 19); // We only take the HH:MM:SS part
|
sb.append("&y[")
|
||||||
sb.append(" ");
|
.append(time, 11, 19) // We only take the HH:MM:SS part
|
||||||
sb.append(packet.getChatter());
|
.append("]&n")
|
||||||
sb.append(" : ");
|
.append(" ")
|
||||||
sb.append(packet.getContent());
|
.append(packet.getChatter())
|
||||||
System.out.println(sb);
|
.append(" : ")
|
||||||
|
.append(packet.getContent()).append("&n"); // make the color back to normal at the end of every message
|
||||||
|
System.out.println(ANSIColor.formatString(sb.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -84,8 +80,6 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitPacket(RoomListPacket packet) {
|
public void visitPacket(RoomListPacket packet) {
|
||||||
// System.out.println("Handled room list !");
|
|
||||||
// throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");
|
|
||||||
System.out.println("Rooms :");
|
System.out.println("Rooms :");
|
||||||
for (String room : packet.getRoomNames()) {
|
for (String room : packet.getRoomNames()) {
|
||||||
System.out.println("\t" + room);
|
System.out.println("\t" + room);
|
||||||
@@ -99,7 +93,14 @@ public class ClientConnexion implements PacketVisitor, PacketHandler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitPacket(ServerResponsePacket packet) {
|
public void visitPacket(ServerResponsePacket packet) {
|
||||||
|
if(packet.getResponse() == ServerResponsePacket.Response.MessageSent || packet.getResponse() == ServerResponsePacket.Response.MessageNotSent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
System.out.println(packet.getResponse());
|
System.out.println(packet.getResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPacket(HandshakePacket packet) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
ChatApp/src/network/protocol/ANSIColor.java
Normal file
18
ChatApp/src/network/protocol/ANSIColor.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package network.protocol;
|
||||||
|
|
||||||
|
public class ANSIColor {
|
||||||
|
public static final String RESET = "\u001B[0m";
|
||||||
|
public static final String BLACK = "\u001B[30m";
|
||||||
|
public static final String RED = "\u001B[31m";
|
||||||
|
public static final String GREEN = "\u001B[32m";
|
||||||
|
public static final String BLUE = "\u001B[34m";
|
||||||
|
public static final String GREY = "\u001B[37m";
|
||||||
|
|
||||||
|
public static String formatString(String message){
|
||||||
|
return message.replace("&r", RED)
|
||||||
|
.replace("&g", GREEN)
|
||||||
|
.replace("&b", BLUE)
|
||||||
|
.replace("&y", GREY)
|
||||||
|
.replace("&n", RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
package network.protocol;
|
package network.protocol;
|
||||||
|
|
||||||
import network.protocol.packets.ChatMessagePacket;
|
import network.protocol.packets.*;
|
||||||
import network.protocol.packets.CreateRoomPacket;
|
|
||||||
import network.protocol.packets.JoinRoomPacket;
|
|
||||||
import network.protocol.packets.LeaveRoomPacket;
|
|
||||||
import network.protocol.packets.LoginPacket;
|
|
||||||
import network.protocol.packets.RequestRoomListPacket;
|
|
||||||
import network.protocol.packets.RoomListPacket;
|
|
||||||
import network.protocol.packets.SendChatMessagePacket;
|
|
||||||
import network.protocol.packets.ServerResponsePacket;
|
|
||||||
|
|
||||||
public interface PacketVisitor {
|
public interface PacketVisitor {
|
||||||
|
|
||||||
@@ -25,5 +17,5 @@ public interface PacketVisitor {
|
|||||||
void visitPacket(RoomListPacket packet);
|
void visitPacket(RoomListPacket packet);
|
||||||
void visitPacket(SendChatMessagePacket packet);
|
void visitPacket(SendChatMessagePacket packet);
|
||||||
void visitPacket(ServerResponsePacket packet);
|
void visitPacket(ServerResponsePacket packet);
|
||||||
|
void visitPacket(HandshakePacket packet);
|
||||||
}
|
}
|
||||||
|
|||||||
14
ChatApp/src/network/protocol/packets/HandshakePacket.java
Normal file
14
ChatApp/src/network/protocol/packets/HandshakePacket.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package network.protocol.packets;
|
||||||
|
|
||||||
|
import network.protocol.Packet;
|
||||||
|
import network.protocol.PacketVisitor;
|
||||||
|
|
||||||
|
public class HandshakePacket extends Packet {
|
||||||
|
public HandshakePacket() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(PacketVisitor packetVisitor) {
|
||||||
|
packetVisitor.visitPacket(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ public class Server implements PacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException {
|
public void joinRoom(String roomName, ServerConnexion connexion) throws SocketException {
|
||||||
if(roomNames.containsKey(roomName)) {
|
if(roomNames.containsKey(roomName) && !roomNames.get(roomName).contains(connexion)) {
|
||||||
roomNames.get(roomName).add(connexion);
|
roomNames.get(roomName).add(connexion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,7 @@ import java.net.SocketException;
|
|||||||
import network.SocketWriter;
|
import network.SocketWriter;
|
||||||
import network.protocol.Packet;
|
import network.protocol.Packet;
|
||||||
import network.protocol.PacketVisitor;
|
import network.protocol.PacketVisitor;
|
||||||
import network.protocol.packets.ChatMessagePacket;
|
import network.protocol.packets.*;
|
||||||
import network.protocol.packets.CreateRoomPacket;
|
|
||||||
import network.protocol.packets.JoinRoomPacket;
|
|
||||||
import network.protocol.packets.LeaveRoomPacket;
|
|
||||||
import network.protocol.packets.LoginPacket;
|
|
||||||
import network.protocol.packets.RequestRoomListPacket;
|
|
||||||
import network.protocol.packets.RoomListPacket;
|
|
||||||
import network.protocol.packets.SendChatMessagePacket;
|
|
||||||
import network.protocol.packets.ServerResponsePacket;
|
|
||||||
import network.protocol.packets.ServerResponsePacket.Response;
|
import network.protocol.packets.ServerResponsePacket.Response;
|
||||||
|
|
||||||
public class ServerConnexion implements PacketVisitor {
|
public class ServerConnexion implements PacketVisitor {
|
||||||
@@ -107,7 +99,6 @@ public class ServerConnexion implements PacketVisitor {
|
|||||||
public void visitPacket(SendChatMessagePacket packet) {
|
public void visitPacket(SendChatMessagePacket packet) {
|
||||||
try {
|
try {
|
||||||
server.sendToRoom(this, packet);
|
server.sendToRoom(this, packet);
|
||||||
sendPacket(new ServerResponsePacket(Response.MessageSent));
|
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
sendPacket(new ServerResponsePacket(Response.MessageNotSent));
|
sendPacket(new ServerResponsePacket(Response.MessageNotSent));
|
||||||
}
|
}
|
||||||
@@ -119,4 +110,10 @@ public class ServerConnexion implements PacketVisitor {
|
|||||||
throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");
|
throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPacket(HandshakePacket packet) {
|
||||||
|
System.out.println("[Server] Handshake received from " + clientAddress);
|
||||||
|
sendPacket(new HandshakePacket());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user