kevinpirola
26-07-2011, 03:17
Ciao a tutti, sto provado ad implementare un piccolo giochetto, ho pensato, per velocizzare la comunicazione tra server e client (soprattutto sui movimenti) che il server potesse inviare i messaggi ai vari client in multicast tramite il socket MulticastSocket che è un estensione del DatagramSocket, questo invece di usare la normale classe Socket e ServerSocket per creare il collegamento client-server (o meglio, non solo). In questo modo nel server era presente un solo MulticastSocket che comunicava con tutti i client che mi interessavano.
Faccio un esempio pratico anche se esula un po' da quello che devo fare io ma è molto simile e poi vi pongo la domanda.
Classico tilemap based game MMORPG.
In ogni mappa ci sono X utenti, quando l'utente x1 si muove manda un messaggio al server (in tcp tramite Socket e ServerSocket), il server lo riceve, lo elabora e lo rigira a tutti i client connessi ad una lista (in questo caso tutti gli X utenti connessi a quella mappa, x1 compreso) in modo che tutti vedano il movimento.
Questo si può fare sia con una ArrayList<Socket> dei vari socket (o meglio ci sarà una classe SocketHandler, ma il concetto è quello) e inviare con un ciclo il messaggio one-to-one ad ogni client, oppure si può fare tramite MulticastSocket.
Sul primo sono abbastanza navigato, sul secondo molto meno.
però a me interesserebbe molto fare arrivare le informazioni ai vari client allo stesso tempo (o almeno tempi confrontabili).
Non sono sicuro però sull'implementazione, infatti, nel TCP normale avevo due classi diverse (ServerSocket e Socket) il Socket si connetteva al ServerSocket in ascolto. Il ServerSocket generava quindi un Socket che "linkava" al Socket del client stabilendo la comunicazione in andata e ritorno.
Con il MulticastSocket invece mi ritrovo una singola classe, perciò non c'è nessuno che fa da server rispetto ad un altro così ho fatto una prova di implementazione mooolto basilare e volevo avere la vostra opinione:
public class Multicast{
public static void main(String[] arg) {
byte[] buffer = new byte[65535];
try {
int port = 5000;
MulticastSocket sock = new MulticastSocket(5000);
InetAddress addr = InetAddress.getByName("235.0.0.1");
sock.joinGroup(addr);
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, addr, port);
sock.receive(packet);
String address = packet.getAddress().toString();
InetAddress client = packet.getAddress();
int client_port = packet.getPort();
System.out.println("Received : '" + new String(buffer).trim() + "' from " + address + "\n");
// send information to the client, questa parte al momento non è utilizzata, i messaggi sono inviati dallo shooter
//String message = "RECEIVED";
//buffer = message.getBytes();
//packet = new DatagramPacket(buffer, buffer.length, client, client_port);
//sock.send(packet);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class MulticastMessageShooter {
public static void main(String[] arg) {
MulticastSocket s1;
byte[] buffer = new byte[65535];
try {
s1 = new MulticastSocket(5000);
int port = 5000;
InetAddress addr = InetAddress.getByName("235.0.0.1");
s1.joinGroup(addr);
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, addr, port);
String(buffer).trim() + "' from " + address + "\n");
String message = "RECEIVED";
buffer = message.getBytes();
packet = new DatagramPacket(buffer, buffer.length, addr, 5000);
s1.send(packet);
}
} catch (IOException e) {
// DONOTHING
}
}
}
Io lancio 3 o 4 istanze della prima classe e poi faccio andare per un tot la classe shooter che mi spara qualche messaggio Multicast. Se poi vado a leggere, tutte le istanze hanno ricevuto i messaggi.
Il fatto è che non ho differenze tra client e server, l'unica cosa che mi viene in mente è che magari il server invia e basta (perciò non implemento il ciclo in ascolto) e il client riceve e basta, le altre comunicazioni che dovrebbero avvenire singole (il client manda le coordinate al server e solo al server, poi il server le checka, se sono buone manda il comando di movimento alle gui e perciò anche alla gui di colui che ha inviato il messaggio, facendo muovere il personaggio, altrimenti non manda alcun messaggio (e il personaggio non si muove)) avvengono tramite ServerSocket e Socket in TCP.
Sono giusto con i ragionamenti? Mi sembra un po' troppo aperta la MulticastSocket, e poi quell'IP là che sta nel famoso range tra 224.0.0.0 e 239.255.255.255 come lo scelgo? non c'è possibilità che tra quegli ip ci sia qualcuno che invia messaggi? devo codificare ogni messaggio?
Attendo vs risposte di qualsiasi tipo, anche se sono critiche sul codice sono molto ben accette
Faccio un esempio pratico anche se esula un po' da quello che devo fare io ma è molto simile e poi vi pongo la domanda.
Classico tilemap based game MMORPG.
In ogni mappa ci sono X utenti, quando l'utente x1 si muove manda un messaggio al server (in tcp tramite Socket e ServerSocket), il server lo riceve, lo elabora e lo rigira a tutti i client connessi ad una lista (in questo caso tutti gli X utenti connessi a quella mappa, x1 compreso) in modo che tutti vedano il movimento.
Questo si può fare sia con una ArrayList<Socket> dei vari socket (o meglio ci sarà una classe SocketHandler, ma il concetto è quello) e inviare con un ciclo il messaggio one-to-one ad ogni client, oppure si può fare tramite MulticastSocket.
Sul primo sono abbastanza navigato, sul secondo molto meno.
però a me interesserebbe molto fare arrivare le informazioni ai vari client allo stesso tempo (o almeno tempi confrontabili).
Non sono sicuro però sull'implementazione, infatti, nel TCP normale avevo due classi diverse (ServerSocket e Socket) il Socket si connetteva al ServerSocket in ascolto. Il ServerSocket generava quindi un Socket che "linkava" al Socket del client stabilendo la comunicazione in andata e ritorno.
Con il MulticastSocket invece mi ritrovo una singola classe, perciò non c'è nessuno che fa da server rispetto ad un altro così ho fatto una prova di implementazione mooolto basilare e volevo avere la vostra opinione:
public class Multicast{
public static void main(String[] arg) {
byte[] buffer = new byte[65535];
try {
int port = 5000;
MulticastSocket sock = new MulticastSocket(5000);
InetAddress addr = InetAddress.getByName("235.0.0.1");
sock.joinGroup(addr);
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, addr, port);
sock.receive(packet);
String address = packet.getAddress().toString();
InetAddress client = packet.getAddress();
int client_port = packet.getPort();
System.out.println("Received : '" + new String(buffer).trim() + "' from " + address + "\n");
// send information to the client, questa parte al momento non è utilizzata, i messaggi sono inviati dallo shooter
//String message = "RECEIVED";
//buffer = message.getBytes();
//packet = new DatagramPacket(buffer, buffer.length, client, client_port);
//sock.send(packet);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class MulticastMessageShooter {
public static void main(String[] arg) {
MulticastSocket s1;
byte[] buffer = new byte[65535];
try {
s1 = new MulticastSocket(5000);
int port = 5000;
InetAddress addr = InetAddress.getByName("235.0.0.1");
s1.joinGroup(addr);
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, addr, port);
String(buffer).trim() + "' from " + address + "\n");
String message = "RECEIVED";
buffer = message.getBytes();
packet = new DatagramPacket(buffer, buffer.length, addr, 5000);
s1.send(packet);
}
} catch (IOException e) {
// DONOTHING
}
}
}
Io lancio 3 o 4 istanze della prima classe e poi faccio andare per un tot la classe shooter che mi spara qualche messaggio Multicast. Se poi vado a leggere, tutte le istanze hanno ricevuto i messaggi.
Il fatto è che non ho differenze tra client e server, l'unica cosa che mi viene in mente è che magari il server invia e basta (perciò non implemento il ciclo in ascolto) e il client riceve e basta, le altre comunicazioni che dovrebbero avvenire singole (il client manda le coordinate al server e solo al server, poi il server le checka, se sono buone manda il comando di movimento alle gui e perciò anche alla gui di colui che ha inviato il messaggio, facendo muovere il personaggio, altrimenti non manda alcun messaggio (e il personaggio non si muove)) avvengono tramite ServerSocket e Socket in TCP.
Sono giusto con i ragionamenti? Mi sembra un po' troppo aperta la MulticastSocket, e poi quell'IP là che sta nel famoso range tra 224.0.0.0 e 239.255.255.255 come lo scelgo? non c'è possibilità che tra quegli ip ci sia qualcuno che invia messaggi? devo codificare ogni messaggio?
Attendo vs risposte di qualsiasi tipo, anche se sono critiche sul codice sono molto ben accette