编写一个java服务端程序以及一个java客户端程序,使得其能在同一端口号下同时接收多台客户端设备连接,并且能根据客户端发送信息为客户端两两配对,使两两配对的客户端能传递信息且不被其他客户端干扰
时间: 2024-03-11 21:51:07 浏览: 76
好的,这是一个相对复杂的问题,需要分步骤解决。下面是一个简单的实现方式:
1. 服务端程序
首先,我们需要编写一个服务端程序,它将监听指定的端口并接受客户端连接请求。每当一个客户端连接到服务器,我们需要将其添加到一个等待队列中,等待其他客户端的连接。
```java
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
private ServerSocket serverSocket;
private List<Socket> clients;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
clients = new ArrayList<>();
System.out.println("Server started on port " + port);
}
public void start() {
while (true) {
try {
Socket clientSocket = serverSocket.accept();
System.out.println("New client connected: " + clientSocket.getInetAddress());
clients.add(clientSocket);
new Thread(new ClientHandler(this, clientSocket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public List<Socket> getClients() {
return clients;
}
public static void main(String[] args) throws IOException {
int port = 12345;
Server server = new Server(port);
server.start();
}
}
```
注意,我们创建了一个名为clients的列表,用于存储所有连接到服务器的客户端套接字。
2. 客户端程序
接下来,我们需要编写一个客户端程序,它将连接到服务器并等待与其他客户端配对。当客户端连接到服务器时,它将发送一个消息,表示它正在等待配对。我们将使用线程来监听从服务器接收的消息并将其显示在屏幕上。
```java
import java.io.*;
import java.net.*;
import java.util.*;
public class Client {
private String name;
private Socket socket;
private BufferedReader input;
private PrintWriter output;
private boolean waiting;
public Client(String name, String address, int port) throws IOException {
this.name = name;
socket = new Socket(address, port);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(socket.getOutputStream(), true);
waiting = true;
output.println("WAITING");
}
public void start() {
new Thread(() -> {
try {
while (true) {
String message = input.readLine();
if (message.startsWith("MATCHED")) {
String[] tokens = message.split(":");
String peerName = tokens[1];
Socket peerSocket = new Socket(tokens[2], Integer.parseInt(tokens[3]));
new Thread(new PeerHandler(peerSocket)).start();
System.out.println("You are now matched with " + peerName);
waiting = false;
} else {
System.out.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
try {
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String message = keyboard.readLine();
if (waiting) {
System.out.println("You are still waiting for a match.");
} else if (message.equals("QUIT")) {
output.println("QUIT");
break;
} else {
output.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class PeerHandler implements Runnable {
private Socket peerSocket;
private BufferedReader input;
private PrintWriter output;
public PeerHandler(Socket peerSocket) throws IOException {
this.peerSocket = peerSocket;
input = new BufferedReader(new InputStreamReader(peerSocket.getInputStream()));
output = new PrintWriter(peerSocket.getOutputStream(), true);
}
@Override
public void run() {
try {
while (true) {
String message = input.readLine();
if (message == null) {
break;
}
System.out.println(name + ": " + message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
peerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendMessage(String message) {
output.println(message);
}
}
public static void main(String[] args) throws IOException {
String name = "Alice";
String address = "localhost";
int port = 12345;
Client client = new Client(name, address, port);
client.start();
}
}
```
3. 服务端和客户端处理程序
现在,我们需要编写两个处理程序,分别用于处理服务端和客户端之间的通信。服务端处理程序将从等待队列中选择两个客户端,将它们配对,并发送一条消息给它们,表示它们已经配对成功。客户端处理程序将监听从服务器接收的消息,如果接收到匹配消息,则将创建一个新的套接字与匹配的客户端连接,并在两个客户端之间传递消息。
```java
import java.io.*;
import java.net.*;
import java.util.*;
public class ClientHandler implements Runnable {
private Server server;
private Socket socket;
private BufferedReader input;
private PrintWriter output;
public ClientHandler(Server server, Socket socket) throws IOException {
this.server = server;
this.socket = socket;
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(socket.getOutputStream(), true);
}
@Override
public void run() {
try {
while (true) {
String message = input.readLine();
if (message == null || message.equals("QUIT")) {
output.println("BYE");
break;
} else if (message.equals("WAITING")) {
Socket peerSocket = null;
synchronized (server.getClients()) {
while (peerSocket == null) {
if (server.getClients().size() == 1) {
output.println("WAITING FOR ANOTHER CLIENT...");
server.getClients().wait();
} else {
int index = new Random().nextInt(server.getClients().size());
Socket peer = server.getClients().get(index);
if (peer != socket) {
peerSocket = peer;
server.getClients().remove(peer);
}
}
}
}
output.println("MATCHED:" + peerSocket.getInetAddress().getHostName() + ":" + peerSocket.getPort());
new Thread(new PeerHandler(socket, peerSocket)).start();
new Thread(new PeerHandler(peerSocket, socket)).start();
} else {
System.out.println(socket.getInetAddress() + ": " + message);
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class PeerHandler implements Runnable {
private Socket socket;
private Socket peerSocket;
private BufferedReader input;
private PrintWriter output;
public PeerHandler(Socket socket, Socket peerSocket) throws IOException {
this.socket = socket;
this.peerSocket = peerSocket;
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(peerSocket.getOutputStream(), true);
}
@Override
public void run() {
try {
while (true) {
String message = input.readLine();
if (message == null || message.equals("QUIT")) {
break;
}
output.println(message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
peerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
```
完成上述步骤后,您将能够编写一个Java服务端程序和一个Java客户端程序,使其能在同一端口号下同时接收多台客户端设备连接,并且能根据客户端发送信息为客户端两两配对,使两两配对的客户端能传递信息且不被其他客户端干扰。
阅读全文