multiple Servers TCP in java - java

I am writing a networked multi player game where players use their own client and server handles all the data processing...
I have finished writing for the game with one server.
What I want to do is, I will have a main server which will send information about different game rooms and players will be able to connect to the game room they want.
What I have in mind is if player click set up new game room, the client will tell server to set up new game which will create a new server and add the information about that server to the main server.
I am keeping secondary servers as ArrayList...
String line = in.nextLine();
if (line.equalsIgnoreCase("new game")) {
servers.add(new SecondaryServers(secondaryPort)); // starting secondary server
secondaryPort++; // this is to keep track of port number
System.out.println(i + " secondary server(s) started"); // printout in main server's console
}
When I do it that way, it started a new server at the first time, but it never goes to the state to print out to the console.
Please help me out to create new servers from the main one :)

I think there is a ServerSocket.accept() method is called from within SecondaryServers. accept() is a blocking method so you should start SecondaryServers in a new Thread.

Related

Sending Player to another Server through Bungee

So I've tried to send players to the lobby server when they type "/lobby" by using this code:
Bukkit.getServer().dispatchCommand((Player) player, "server lobby");
But in game, it returns "Unknown Command. Type "/help" for help."
I've also read to try this code, but I don't know what to put in place of "a", "b", and "c"
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("a");
out.writeUTF("b");
//applies to the player you send it to. aka Kick To Server.
Player player = Bukkit.getPlayerExact("c");
player.sendPluginMessage(this, "BungeeCord", out.toByteArray());
So my question is why does the first method not work? Also, how do you make the second solution work? Is there code I need to put in the bungee server?
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect");
out.writeUTF("ServerName");
player.sendPluginMessage(PluginObject, "BungeeCord", out.toByteArray());
This is what you are looking for. To answer your question, "a" is always "Connect". "b" is the name of the server that you want to connect to (In your case this is "lobby"), and "c" will the name of the player (This is because in the example that you've supplied your getting the player by their name, however if you've already got the player object, this isn't needed).
And just so that you understand why dispatchCommand doesn't work, it's because when you do /server on your client it sends a packet to the Bungeecord as that's what your client is connected to, and it will intercept that command packet read it and see that it's a server command. It will then proceed to connect you to the right server. If you use dispatchCommand on the Bukkit server it will execute the command as though it just received an command packet, which means it never sends out any sort of message to the bungeecord or to the client to get it to execute a command. The dispatchCommand method will only be run on the bukkit server.
The reason that the second solution works is because in the Minecraft protocol there's this thing called the plugin messaging channel, for custom messages between the client and the server. And yet again as the Bungeecord sits in the middle of the client and the server, it listens on certain messages, and any of them tagged with Connect will connect a player to the specified server. I hope this makes sense.

How do I communicate with all threads on a Multithreaded server?

Ok. I'm trying to grasp some multithreading Java concepts. I know how to set up a multiclient/server solution. The server will start a new thread for every connected client.
Conceptually like this...
The loop in Server.java:
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress() + " connected");
new ClientHandler(socket).start();
}
The ClientHandler.java loop is:
while(true)
{
try {
myString = (String) objectInputStream.readObject();
}
catch (ClassNotFoundException | IOException e) {
break;
}
System.out.println(myClientAddress + " sent " + myString);
try {
objectOutputStream.writeObject(someValueFromTheServer);
objectOutputStream.flush();
}
catch (IOException e) {
return;
}
}
This is just a concept to grasp the idea. Now, I want the server to be able to send the same object or data at the same time - to all clients.
So somehow I must get the Server to speak to every single thread. Let's say I want the server to generate random numbers with a certain time interval and send them to the clients.
Should I use properties in the Server that the threads can access? Is there a way to just call a method in the running threads from the main thread? I have no clue where to go from here.
Bonus question:
I have another problem too... Which might be hard to see in this code. But I want every client to be able to receive messages from the server AND send messages to the sever independently. Right now I can get the Client to stand and wait for my gui to give something to send. After sending, the Client will wait for the server to send something back that it will give to the gui. You can see that my ClientHandler has that problem too.
This means that while the Client is waiting for the server to send something it cannot send anything new to the server. Also, while the Client is waiting for the gui to give it something to send, it cannot receive from the server.
I have only made a server/client app that uses the server to process data it receives from the Client - and the it sends the processed data back.
Could anyone point me in any direction with this? I think I need help how to think conceptually there. Should I have two different ClientHandlers? One for the instream and one for the outstream? I fumbling in the dark here.
"Is there a way to just call a method in the running threads from the main thread?"
No.
One simple way to solve your problem would be to have the "server" thread send the broadcast to every client. Instead of simply creating new Client objects and letting them go (as in your example), it could keep all of the active Client objects in a collection. When it's time to send a broadcast message, it could iterate over all of the Client objects, and call a sendBroadcast() method on each one.
Of course, you would have to synchronize each client thread's use of a Client object outputStream with the server thread's use of the same stream. You also might have to deal with client connections that don't last forever (their Client objects must somehow be removed from the collection.)

How to write java TCP object transmission for multiple clients

I'm writing a primitive Graphical MUD-like online game using only the Java standard library - just Swing and TCP sockets (for school and for fun). The game has a server (a spare laptop in my closet) that accepts TCP connections from players and takes in objects (using ObjectInputStream) - chat strings and dropped items and such - and uses those objects to make changes to the virtual world that are then forwarded to the other players.
Initially, I thought I could make each and every player connect to the same TCP port on my server (port 5010) by having my server's main thread listen for each of their connections using a loop, like so...
while (true)
{
//get new connection
serversocket = new ServerSocket(5010);
socket = serversocket.accept();
serversocket.close();
//proceed to log in player using their computer's host name.
}
Then I pass each new player's TCP socket connection to a thread dedicated to that player's object input and output, like so:
new_thread = new Thread(new Server_Input_Thread(main_thread_socket));
When I'm debugging, I test the game by running both the server side application and the client side application from my other laptop and connect through "localhost".
But I'm having problems. I can't get past IOExceptions such as Bind exceptions and "java.net.SocketException: socket closed" when listening for a new connection (on port 5010) after the initial connection (also on port 5010) has been made.
Apparently the way I'm doing it isn't working and perhaps I'll need to assign each player a unique port number rather than have every player try to connect to port 5010, or maybe it's because I'm using my coding laptop as both a client and a server.
Unfortunately for me, I have no idea what I'm doing - I just declared Computer Science as my major one semester ago. Please explain how to structure the network connections for such a virtual world and avoid the IOExceptions that occur immediately after the initial connection between the client application and the server, as the server is starting to once again listen for a new connection on port 5010 on the main thread.
Try this
serversocket = new ServerSocket(5010);
while (true)
{
socket = serversocket.accept();
//proceed to log in player using their computer's host name.
}
serversocket.close();
I am not going to show you the other problems you are going to face but this should at least get you going.

Setting up a multi-client/server TCP connection in Java

I'm trying to create a multi-client/server application in Java. I'm having quite some issues because my threads seem to get entangled... Here's what I'm trying to do.
I have a Server-class that accepts clients by using this piece of code:
while(true){
Socket socket = serverSocket.accept();
}
My server should remember the clients that are connected so I create a new Thread called ClientThread with that socket and place that Thread in a List on the Server
That Thread listens to Command-objects that are sent from the client. If it receives a Command, it needs to send it to the Server instance for further processing (without creating a new instance of Server on that ClientThread). I've tried to do this by adding the Server-instance to this Thread when it's created. (Is this the right way?)
My Server should also be able to send Objects back to the clients (1 or more) at any time. I'm trying to do this by using socket.getOutputStream() that is kept in the ClientThread
How should I organize my Threads so that every client is constantly listening to accept objects from the server AND that they can send objects to the Server at any time.
I know this isn't really a specific question, but if you know some info or tutorials that might be helpful for this use case, I'd be really thankful.
btw: I know how to create sockets and send (serializable) objects and so on.. I'm just stuck on how to organize everything
You appear to have tangled Thread and objects. I would
a) make sure you are not extending Thread anywhere or calling your objects XxxxThread. Using an ExecutorService to manage your threads is a good idea.
b) have a simple model for responding to client commands, e.g. each client thread reads a task and then performs a task.
c) Have a wrapper for each connections, e.g. with a sendMessage method.
Since you already know about sockets and threads, I send you the idea pseudo code (case need a specific part of code just let me know)
One thing you did not mention is how to keep track of clients, by its IP o by any other method like an ID? Can any given device open more than one connection with different client ID? Or you'll only accept one connection per device? In any case, if a client is already in the list, what do you suposse to do? Will you communicate the created thread the new socket? Will you destroy that thread and create a new one? Or maybe you'll ignore this new request?
This is my idea (taken from a working application):
Server prepares the server socket and wait in the accept state.
Once a client connects, the server start a thread to attend the client passing the socket it just created with the accept command. When the thread which attends the client starts, the very first message it receives from the client should be a password o special signature to let the client gets in (this is optional).
Server code:
Prepares the server socket which listen in a well known port
Clear client list;
While (!Terminated)
{
// if you want to impose a limit for connections, check it here:
if (Is the list of connected client full?)
{
Sleep(reasonable time in seconds or miliseconds);
continue;
}
ClientSocket = ServerSocket.Accept();
if the client's IP is already in the list
{
depends on what you want to do.
}
else
{
Add client's IP to the list
Start (create) new client Tread(ClientSocket);
}
}
// when server finish
If (client list is not empty?)
{
Kill all threads
or
Wait until all threads are done
or
Wait an amount of time and then kill those remaining.
}
thread client code:
// This is optional, just to make sure a valid client is connected
Read packet from ClientSocket
if (!Is_the_passport_packet)
{
close socket;
return;
}
// if passport is not required, start here
Try
{
While (!Terminated)
{
if (read packet from client);
{
switch (packet.Command)
{
// In your question you said you want the Server thread to process the request
// I guess you have your requirements to do so,
// anyway, you must use a mutex o some other synchronization method.
case TASK_1:
[sync] process TASK_1(packet, ClientSocket);
break;
case TASK_2:
[sync] process TASK_2(packet, ClientSocket);
break;
etc ….
case WORK_DONE:
Close Socket;
return;
default:
Log(received an unknown command: packet.command);
break;
}
}
else if (Client has quit (closed/broken socket))
{
// as you may know, a socket is consider shutdown when you received a 0 length data
// and a broken connection when received -1 in either case all you have to do is
Close Socket;
return;
}
}
}
catch (Exception e)
{
Log(received an exception: e.message);
}
finally
{
Remove this client from the client's list
}

actionListener using in Memory Game Client - server application

I'm solving one problem and I've kinda stucked. I'll start with some background.
I'm programing memory game (for example it is something like this http://www.mathsisfun.com/games/memory/index.html). It should be client-server aplication.
client - in java
server - in C
situation is 1 server, N clients
server will have list of games - in each game two players
each game will be separately process in onw process - i use fork
client is java swing form aplication - and represets players
clients and server comunicate only with two methods (resp. functions)
client - void sendMessageToServer(String message), String recieveMessageFromerver()
server - recieveMessage(void *vptr, size_t maxlen,
int socketfileDesc) ,int sendMessageToClient(char* msg, int socket)
simply - i just send string messages from server to client, client to server I which are coded actions
Now my problem:
For easier testing client side a made server also in java, and I solve problem only with one game - one server, 2 clients (both in java)
so I have 3 classes
Clilent:
- show the from,
- has info about game,
- has static method CreateAndShowGUI(String serverInsanceHandle) => show - the form, make instance of client
Server:
- just two messages - recieve, send i mentioned before
Test:
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
final Server server = new Server();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
Client.createAndShowGUI(server);
Client.createAndShowGUI(server);
}
});
}
}
HERE:
My problem is this:
for simple testing I have game 4x4 cards this mean 8 pairs
I have array JButton[] buttonsArray = new JButton[16]; on each button is ImageIcon with picture of card, each button have added actionListenner(privateClass)
in privateClass which implements ActionListener is method actionPerformed and there I change set up of the client- I send message to server and server send me back message what I should do in client.
My problem is that I have two clients and one server.
When I make action in client1, it have effect only in client1, but I need somehow let now it to client2.
I can have field of cards what should be viewed on serverside,or I can have field of String messages - with coded changes, but I don't now how to let client2 know that client1 did some action. Comunication must be trough server:
Something like "Hello I'm client1 and I pressed button number 2 so you client2 should ask server for changes" but I' can't do this.
So what can I do?
NOTE: It should be "simulation" of TCP communication, so I'll use tcp sockets - but this is probably not important now.
I'm going to assume two things about your server:
The Server is maintaining the state of the Memory game (IE, which cards are currently flipped over, which client discovered correct pairs of cards, etc.). I'm going to call this the GameState object.
The Server also maintains a unique Socket connection to each Client
It sounds to me like your clients first update their own local GameState, then tell the server to update its GameState. That said, I'd make the following changes:
Each time a client wants to flip a card, or some other action that modifies the GameState, have it send a message to the Server, telling it to update its GameState.
Whenever the Server updates its GameState, have it send the entire GameState to all Clients.
Design your client to only show GameState that it has received from the server.
This way, your server can control the master GameState and your clients act more like "observers" of that GameState.

Categories

Resources