Je suis nouveau dans la programmation Socket en Java et je cherchais à comprendre si le code ci-dessous n’est pas une mauvaise chose à faire. Ma question est:
Puis-je avoir plusieurs clients sur chaque thread essayant de se connecter à une instance de serveur dans le même programme et m'attendre à ce que le serveur lise et écrit des données avec une isolation entre les clients "
public class Client extends Thread
{
...
void run()
{
Socket socket = new Socket("localhost", 1234);
doIO(socket);
}
}
public class Server extends Thread
{
...
void run()
{
// serverSocket on "localhost", 1234
Socket clientSock = serverSocket.accept();
executor.execute(new ClientWorker(clientSock));
}
}
Puis-je avoir plusieurs instances de client sur différents threads essayant de se connecter sur le même port de la machine actuelle?
Par exemple,
Server s = new Server("localhost", 1234);
s.start();
Client[] c = new Client[10];
for (int i = 0; i < c.length; ++i)
{
c.start();
}
Oui, cependant un seul client pourra se connecter par exécution de thread telle que écrite.
Vous pouvez simplement placer votre serveur run () dans une boucle while true afin de permettre à plusieurs clients de se connecter. Selon l’exécutant, ils s’exécuteront en série ou en parallèle.
public class Server extends Thread
{
...
void run()
{
while(true){
// serverSocket on "localhost", 1234
Socket clientSock = serverSocket.accept();
executor.execute(new ClientWorker(clientSock));
}
}
}
Tant qu'un seul objet essaie de lier le port pour l'écoute, la connexion de plusieurs clients ne pose aucun problème.
Dans cet exemple, votre Server
accepte et gère une connexion client à la fois. Vous pouvez avoir autant de Client
s que vous voulez essayer de vous connecter, mais un seul à la fois sera traité.
Il n'est pas évident que votre logique d'exécution soit multithread, car vous n'avez pas fourni l'implémentation. Si l'exécuteur délègue à un pool de threads ou quelque chose du genre, vous devez vous assurer que votre ClientWorker
est thread-safe, dans la mesure où plusieurs instances s'exécutent en parallèle.
Bien entendu, je suppose que votre Client
est également thread-safe, puisque votre question ne concerne que le Server
.
Oui, peu importe que vos clients soient locaux ou distants. Dans votre exemple, l’important est que ClientWorker respecte les threads, car votre serveur disposera de plusieurs instances de cette classe (une pour chaque connexion client).
Vous pouvez essayer quelque chose sur ces lignes
public class MultiThreadServer extends Application {
// Text area for displaying contents
private TextArea ta = new TextArea();
// Number a client
private int clientNo = 0;
@Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a scene and place it in the stage
Scene scene = new Scene(new ScrollPane(ta), 450, 200);
primaryStage.setTitle("MultiThreadServer"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
new Thread( () -> {
try {
// Create a server socket
ServerSocket serverSocket = new ServerSocket(8000);
ta.appendText("MultiThreadServer started at "
+ new Date() + '\n');
while (true) {
// Listen for a new connection request
Socket socket = serverSocket.accept();
// Increment clientNo
clientNo++;
Platform.runLater( () -> {
// Display the client number
ta.appendText("Starting thread for client " + clientNo +
" at " + new Date() + '\n');
// Find the client's Host name, and IP address
InetAddress inetAddress = socket.getInetAddress();
ta.appendText("Client " + clientNo + "'s Host name is "
+ inetAddress.getHostName() + "\n");
ta.appendText("Client " + clientNo + "'s IP Address is "
+ inetAddress.getHostAddress() + "\n");
});
// Create and start a new thread for the connection
new Thread(new HandleAClient(socket)).start();
}
}
catch(IOException ex) {
System.err.println(ex);
}
}).start();
}
// Define the thread class for handling new connection
class HandleAClient implements Runnable {
private Socket socket; // A connected socket
/** Construct a thread */
public HandleAClient(Socket socket) {
this.socket = socket;
}
/** Run a thread */
public void run() {
try {
// Create data input and output streams
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(
socket.getOutputStream());
// Continuously serve the client
while (true) {
// Receive radius from the client
double radius = inputFromClient.readDouble();
// Compute area
double area = radius * radius * Math.PI;
// Send area back to the client
outputToClient.writeDouble(area);
Platform.runLater(() -> {
ta.appendText("radius received from client: " +
radius + '\n');
ta.appendText("Area found: " + area + '\n');
});
}
}
catch(IOException e) {
ex.printStackTrace();
}
}
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
Alors. Pour commencer:
Vous pouvez accepter plusieurs clients avec un serveur de serveur, car vous en acceptez un seul dans la méthode run
-. Il vous suffit d'appeler accept()
une seconde fois.
Ensuite, vous dans votre boucle for: vous devez d’abord créer chaque fois un nouvel objet Client
. Ensuite, vous pouvez appeler c[i].start();
et non pas c.start()
.
Puis-je maintenant avoir plusieurs instances Client Sur différents threads essayant De se connecter sur le même port de la machine Actuelle?
Oui, vous pouvez. Il suffit de créer de nouveaux threads et de les exécuter. Cela devrait fonctionner parfaitement.
attendez du serveur qu'il lise et écrit des données avec isolation entre les clients
Vous pouvez utiliser votre expérience des techniques de base de IO comme avec file-io:
OutputStream os = socket.getOutputStream();
PrintStream pw = new PrintStream(os, true); // Or PrintWriter, I don't know what the best one is.
pw.println("Hello, other side of the connection!");
Et pour lire, utilisez un BufferedReader.