Chat System - Private Messages - Whispers

Introduction: This tutorial is the sixteenth in my Java Network Programming using KryoNet series, or eleventh in creating a chat client and server system, in which we are going to be adding a new command to the user client chat GUI interface. This command will be a private message. Previous: In the previous tutorial we added commands to the server and made the first one which was to kick clients out of the chat room. The System: We are going to give the user a GUI to interact with the system - to send messages and see the currently connected members of the chat. When a client connects, add them to a list. Send incoming messages to everyone within the client list except the sender - or send them one back saying that it is received, as confirmation. This Tutorial: This tutorial we are going to create a new command to send private messages to other clients within the chat room. This command will be Whisper and will require a new packet, create this now...
  1. package Packets;
  2.  
  3. public class Packet6Whisper extends Packet{
  4. public String username, message;
  5. }
This packet takes two strings; the username to send the private message to, and the message to send to them. Ensure you put this new packet in both java projects Packets packages and register the new Packet in both projects as well...
  1. client.getKryo().register(Packet6Whisper.class);
  1. client.getKryo().register(Packet6Whisper.class);
Command: Now add the command to the client chat GUI, append this underneath the first if command check in the send message method...
  1. else if(entered.toLowerCase().startsWith("/whisper")) {
  2. String args[] = entered.split(" ");
  3. if (args.length == 3) {
  4. Packet6Whisper packet = new Packet6Whisper();
  5. packet.username = args[1];
  6. packet.message = args[2];
  7. client.sendTCP(packet);
  8. }else
  9. System.out.println("Incorrect specified parameters. /whisper {user} {message}");
  10. }
As you can see, if the entered whisper command has two additional parameters (three in total), a username and a message, the Packet is created, variables are set and the packet is sent on its way, otherwise we output an error about invalid parameters and output the syntax structure of the command. Server Receiving: Once the server receives the packet, we want to create a Packet2Message packet, [partially now, partially in the next method] set the message to "[PRIVATE MESSAGE FROM " followed by the senders username, followed by "}" and then send it to the client with the specified username (in the packet, sent from the client)...
  1. else if(object instanceof Packet6Whisper) {
  2. Packet6Whisper packet = (Packet6Whisper) object;
  3. Packet2Message msgPacket = new Packet2Message();
  4. msgPacket.message = packet.message;
  5. clientHandler.sendPacketTo(packet.username, msgPacket, connection);
  6. System.out.println("Processing PM to " + packet.username);
  7. }
Now we need to create the sendPacketTo method in our clientHandler. It accepts three arguments; the username to send the packet to, the packet to send, and the connection the request was sent from (to get the username of the sender)...
  1. public void sendPacketTo(String username, Packet2Message msgPacket, Connection connection) {
  2. String fromUser = getUsername(connection);
  3. String mainMessage = msgPacket.message;
  4. msgPacket.message = "[PRIVATE MESSAGE FROM " + fromUser + "] " + mainMessage;
  5. Connection con = getConnection(username);
  6. try {
  7. con.sendTCP(msgPacket);
  8. }catch (Exception ex){
  9. System.out.println(ex);
  10. }
  11. }
As you can see, it gets the from username from the connection parsed, it then amends the message with the appropriate tags and sent from username, gets the connection from the toUsername parsed to it, and send the message packet (Packet2Message). Finally we need to create the method to convert the String username to a KryoNet Connection...
  1. private Connection getConnection(String username) {
  2. for (CustomClient c : this.clients) {
  3. if (c.getUsername().equalsIgnoreCase(username))
  4. return c.getConnection();
  5. }
  6. return null;
  7. }

Add new comment