我是Java中Socket编程的新手,并试图了解下面的代码是不是错误的做法。我的问题是:
我是否可以在每个线程上尝试连接到同一程序中的服务器实例的多个客户端,并期望服务器在客户端之间隔离地读取和写入数据“
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));
}
}
现在我可以在尝试连接当前机器的同一端口的不同线程上有多个客户端实例吗?
例如,
Server s = new Server("localhost", 1234);
s.start();
Client[] c = new Client[10];
for (int i = 0; i < c.length; ++i)
{
c.start();
}
答案 0 :(得分:10)
是的,但是只有一个客户端能够按写入的方式连接每个线程。
您可以将服务器run()置于while循环中,让多个客户端连接。 根据执行者的不同,它们将以串行或并行方式执行。
public class Server extends Thread
{
...
void run()
{
while(true){
// serverSocket on "localhost", 1234
Socket clientSock = serverSocket.accept();
executor.execute(new ClientWorker(clientSock));
}
}
}
答案 1 :(得分:3)
只要您只有一个对象尝试绑定端口进行侦听,那么多个客户端连接就没有问题。
答案 2 :(得分:1)
在此示例中,您的Server
一次接受并处理一个客户端连接。您可以根据需要尝试连接Client
个,但一次只能处理一个。
由于您没有提供实现,因此您的执行程序逻辑是否为多线程并不明显。如果执行程序委托给线程池或类似的东西,则需要确保ClientWorker
是线程安全的,因为你将有多个实例并行执行。
我当然假设您的Client
也是线程安全的,因为您的问题仅涉及Server
。
答案 3 :(得分:0)
是的,您的客户是本地客户还是远程客户并不重要。在您的示例中,重要的是ClientWorker是线程安全的,因为您的服务器将具有该类的多个实例(每个客户端连接一个)。
答案 4 :(得分:0)
因此。开始:
您可以使用一个serversocket接受更多客户端,因为您只接受run
- 方法中的一个。您只需再次拨打accept()
。
然后,你在for循环中:首先你必须每次创建一个新的Client
对象。然后,您可以拨打c[i].start();
而不是c.start()
。
现在可以拥有多个客户端 尝试不同线程上的实例 连接在同一个端口上 当前的机器?
是的,你可以。只需创建新的线程并运行它们。这应该是完美的。
希望服务器能够读写 客户之间隔离的数据
您可以使用基本IO技术的经验,例如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!");
阅读使用BufferedReader。
答案 5 :(得分:0)
你可以尝试这些方面的东西
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);
}
}