aaddddas
Satire Specialist
2
MONTHS
2 2 MONTHS OF SERVICE
LEVEL 1
100 XP
Introduction:
This tutorial is the eleventh in my Java Network Programming using KryoNet series, or sixth in creating a chat client and server system, in which we are going to be ensuring that no two clients have the same username.
Previous:
In the previous tutorial we created a way to circulate any incoming messages to the server to the rest of the clients.
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:
Instead of just sending one PacketConnect from the client to the server, we are going to loop this until the username is not currently connected to the server through an other client.
Packets:
First we are going to create two new packets; Username3Req and Username4Res.
Request will contain the username to check with the server if the username exists. Res will be sent from the server as a response to the clients request packet stating whether the username is available or not.
Req:
Res:
Copy the packets to both projects Packets packages.
Client:
Now we want to edit the client to loop the connection and allow username input from the user...
In the method we use a couple of global variables, create these under the initial class line...
Then in the constructor where we used to have the four lines of PacketConnect (make sure the listener is above this connect call), replace it with running the new method..
This code will loop until the global variables are set correctly where the username is available. We use Thread.sleep(500) to sleep the program for half a second (500ms) while the server response boolean variable in the global scope is false because we do not yet have a response and so we are unable to check whether the username is available or not through the second boolean global variable and we don't want to spam the application with constant running.
Server Listener:
Now we want to handle the Packet from the server listener. First we make sure we are receiving a username request, then we run a method from our ClientHandler (we create this in a second) to return whether the username exists or not, with that information we reply with a UsernameRes (response) packet...
Client Handler userExists method...
Class Registering:
We also need to register the new classes in both the client and server. Put this under the other class registries we have already - TIP: Make sure the client and server registers are in the same order to avoid serialisation errors...
And:
Client Listener:
Finally we need to create our client listener. This will listen out for the username response packet and set the global variables accordingly which in turn will trigger the connect while loop to break (stop sleeping for 500ms) and continue with the attempted login...
This tutorial is the eleventh in my Java Network Programming using KryoNet series, or sixth in creating a chat client and server system, in which we are going to be ensuring that no two clients have the same username.
Previous:
In the previous tutorial we created a way to circulate any incoming messages to the server to the rest of the clients.
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:
Instead of just sending one PacketConnect from the client to the server, we are going to loop this until the username is not currently connected to the server through an other client.
Packets:
First we are going to create two new packets; Username3Req and Username4Res.
Request will contain the username to check with the server if the username exists. Res will be sent from the server as a response to the clients request packet stating whether the username is available or not.
Req:
- package
Packets
;
- public
class
Packet3UsernameReq extends
Packet{
- public
String
username;
- }
Res:
- package
Packets
;
- public
class
Packet4UsernameRes extends
Packet{
- public
boolean
bool;
- }
Copy the packets to both projects Packets packages.
Client:
Now we want to edit the client to loop the connection and allow username input from the user...
- public
void
connect(
Client client)
{
- System
.out
.println
(
"Enter your username for the new chat room... "
)
;
- Scanner userScan =
new
Scanner(
System
.in
)
;
- while
(
true
)
{
- String
loggedInUsername =
userScan.nextLine
(
)
;
- Packet3UsernameReq req =
new
Packet3UsernameReq(
)
;
- req.username
=
loggedInUsername;
- client.sendTCP
(
req)
;
- while
(
!
userServerRes)
{
- try
{
- System
.out
.println
(
"Sleeping..."
)
;
- Thread
.sleep
(
500
)
;
- }
catch
(
Exception
ex)
{
}
- }
- System
.out
.println
(
"+ "
+
userServerAvailable)
;
- if
(
userServerAvailable)
{
- System
.out
.println
(
"That username is already taken. Please enter a new one... "
)
;
- userServerRes =
false
;
//Reset global booleans used for server username response
- }
else
{
//false=available
- System
.out
.println
(
"Connecting..."
)
;
- Packet1Connect con =
new
Packet1Connect(
)
;
- con.name
=
loggedInUsername;
- client.sendTCP
(
con)
;
- System
.out
.println
(
"Connected as "
+
loggedInUsername)
;
- userServerRes =
false
;
//Reset global booleans used for server username response
- break
;
- }
- }
- }
In the method we use a couple of global variables, create these under the initial class line...
- boolean
userServerRes =
false
;
- boolean
userServerAvailable =
false
;
Then in the constructor where we used to have the four lines of PacketConnect (make sure the listener is above this connect call), replace it with running the new method..
- connect(
client)
;
This code will loop until the global variables are set correctly where the username is available. We use Thread.sleep(500) to sleep the program for half a second (500ms) while the server response boolean variable in the global scope is false because we do not yet have a response and so we are unable to check whether the username is available or not through the second boolean global variable and we don't want to spam the application with constant running.
Server Listener:
Now we want to handle the Packet from the server listener. First we make sure we are receiving a username request, then we run a method from our ClientHandler (we create this in a second) to return whether the username exists or not, with that information we reply with a UsernameRes (response) packet...
- else
if
(
object instanceof
Packet3UsernameReq)
{
- Packet3UsernameReq packet =
(
Packet3UsernameReq)
object;
- boolean
userExists =
clientHandler.userExists
(
packet.username
)
;
- Packet4UsernameRes resPacket =
new
Packet4UsernameRes(
)
;
- resPacket.bool
=
userExists;
- connection.sendTCP
(
resPacket)
;
- }
Client Handler userExists method...
- public
boolean
userExists(
String
username)
{
- // Return true if user Exists, false if the username is available.
- for
(
CustomClient c :
this
.clients
)
{
- if
(
c.getUsername
(
)
.toLowerCase
(
)
.equals
(
username.toLowerCase
(
)
)
)
- return
true
;
// Username exists.
- }
- return
false
;
//Username available.
- }
Class Registering:
We also need to register the new classes in both the client and server. Put this under the other class registries we have already - TIP: Make sure the client and server registers are in the same order to avoid serialisation errors...
- server.getKryo
(
)
.register
(
Packet3UsernameReq.class
)
;
- server.getKryo
(
)
.register
(
Packet4UsernameRes.class
)
;
And:
- client.getKryo
(
)
.register
(
Packet3UsernameReq.class
)
;
- client.getKryo
(
)
.register
(
Packet4UsernameRes.class
)
;
Client Listener:
Finally we need to create our client listener. This will listen out for the username response packet and set the global variables accordingly which in turn will trigger the connect while loop to break (stop sleeping for 500ms) and continue with the attempted login...
- else
if
(
object instanceof
Packet4UsernameRes)
{
- Packet4UsernameRes res =
(
Packet4UsernameRes)
object;
- userServerAvailable =
res.bool
;
//Original bool is false if username is available, revert this to true for the variable.
- userServerRes =
true
;
- System
.out
.println
(
"Username response received."
)
;
- }