Ich bin neu in der Socket-Programmierung in Java und habe versucht zu verstehen, ob der folgende Code nicht falsch ist. Meine Frage ist:
Kann ich mehrere Clients in jedem Thread haben, die versuchen, eine Verbindung zu einer Serverinstanz im selben Programm herzustellen, und erwarten, dass der Server Daten mit Isolation zwischen Clients liest und schreibt? "
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));
}
}
Kann ich jetzt mehrere Client-Instanzen in verschiedenen Threads haben, die versuchen, eine Verbindung zum gleichen Port des aktuellen Computers herzustellen?
Zum Beispiel,
Server s = new Server("localhost", 1234);
s.start();
Client[] c = new Client[10];
for (int i = 0; i < c.length; ++i)
{
c.start();
}
Ja, jedoch kann nur ein Client pro Thread-Ausführung eine Verbindung herstellen, wie geschrieben.
Sie können Ihren Server mit run () in eine while-True-Schleife einbinden, damit sich mehrere Clients verbinden können. Je nach Executor werden sie entweder in Reihe oder parallel ausgeführt.
public class Server extends Thread
{
...
void run()
{
while(true){
// serverSocket on "localhost", 1234
Socket clientSock = serverSocket.accept();
executor.execute(new ClientWorker(clientSock));
}
}
}
Solange Sie nur ein Objekt haben, das versucht, den Port für das Abhören zu binden, gibt es kein Problem, wenn mehrere Clients eine Verbindung herstellen.
In diesem Beispiel akzeptiert und verarbeitet Ihre Server
jeweils eine Clientverbindung. Sie können so viele Client
s haben, wie Sie möchten, um eine Verbindung herzustellen, aber es wird jeweils nur eine davon behandelt.
Es ist nicht ersichtlich, ob Ihre Executor-Logik Multithreading ist, da Sie die Implementierung nicht bereitgestellt haben. Wenn der Executor an einen Threadpool oder etwas Ähnliches delegiert, müssen Sie sicherstellen, dass Ihre ClientWorker
threadsicher ist, da mehrere Instanzen parallel ausgeführt werden.
Ich gehe natürlich davon aus, dass Ihre Client
auch Thread-sicher ist, da Ihre Frage nur die Server
betrifft.
Ja, es spielt keine Rolle, ob Ihre Clients lokal oder remote sind. In Ihrem Beispiel ist es wichtig, dass ClientWorker Thread-sicher ist, da Ihr Server über mehrere Instanzen dieser Klasse verfügt (eine für jede Clientverbindung).
Sie können etwas auf diesen Zeilen versuchen
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);
}
}
So. Beginnen:
Sie können mehrere Clients mit einem Serversocket akzeptieren, da Sie nur einen in der run
- Methode akzeptieren. Sie müssen nur noch ein zweites Mal accept()
aufrufen.
Dann sind Sie in Ihrer for-Schleife: Zuerst müssen Sie jedes Mal ein neues Client
-Objekt erstellen. Dann können Sie c[i].start();
und nicht c.start()
aufrufen.
Kann ich jetzt mehrere Client - Instanzen auf verschiedenen Threads haben, die versuchen, An demselben Port des aktuellen Computers anzuschließen?
Ja, du kannst. Erstellen Sie einfach neue Threads und führen Sie sie aus. Das sollte perfekt funktionieren.
erwarten, dass der Server Daten mit Isolierung zwischen Clients liest und schreibt
Sie können Ihre Erfahrung mit den grundlegenden IO-Techniken wie mit file-io verwenden:
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!");
Und zum Lesen verwenden Sie einen BufferedReader.