好的,首先让我给你一个关于套接字如何工作的小背景,然后再给你解决方案,了解发生了什么是至关重要的。
套接字解释(参考)
套接字是在服务器程序和一个或多个客户端程序之间建立双向通信的软件端点。注意双向这个词。这意味着对于客户端和服务器之间的每个连接,您都有两个流:一个输入流和一个输出流。这些可以通过在服务器端和客户端设置的两个套接字对象访问。
你的问题
从服务器到客户端,我只做 player[i].out.writeUTF(message) 和客户端然后检查他的“in”,做 in.readUTF() 并且一切正常。从客户端到服务器,我从客户端执行 out.writeUTF(message),但是在服务器端,我必须选择一个 player[i].in 来读取我不知道哪个玩家是的。
因此,如果我理解正确,您很难确定是哪个客户向您发送了消息。如果您正确使用多线程,这很容易解决,因为每个客户端都将在单独的线程上处理。
一个至关重要的步骤是最初如何处理客户。考虑以下代码。为了保持简短,我没有过多地关注约定。
ArrayList<ClientWorker> clientWorkers = new ArrayList<ClientWorker>();
int idCounter = 0;
public void listenSocket(){
try{
int port = 9090
server = new ServerSocket();
} catch (IOException e) {
System.exit(-1);
}
while(true){
ClientWorker w;
try{
//server.accept returns a client connection
clientWorker = new ClientWorker(server.accept(), idCounter, );
idCounter++;
clientWorkers.add(clientWorker);
Thread t = new Thread(clientWorker);
t.start();
} catch (IOException e) {
System.exit(-1);
}
}
}
好的,通过该代码,我们正在处理新客户并为他们分配一个唯一的密钥。我使用数组列表代替数组,以便它可以根据连接到服务器的用户数量增加和减少大小。收到客户端后,我创建一个 clientWorker 实例。此外,为每个连接的用户分配一个唯一键,可用于从数组列表中获取其对象(如果需要)。
ClientWorker 类看起来像这样:
class ClientWorker implements Runnable {
private Socket client;
public int id
//Constructor
ClientWorker(Socket client, int id) {
this.client = client;
this.id = id;
}
public void run(){
String line;
BufferedReader in = null;
PrintWriter out = null;
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("in or out failed");
System.exit(-1);
}
while(true){
try{
//ANY DATA I GET FROM THIS STREAM IS FROM THIS PARTICULAR CLIENT ONLY!
line = in.readLine();
System.out.println("RECEIVED FROM CLIENT "+ id +" " + line);
}catch (IOException e) {
System.exit(-1);
}
}
}
}
该线程调用 run() 方法。由于每个客户端都有一个单独的线程,因此从特定线程处理的数据是从该特定客户端而不是其他人发送的。因此,可以很容易地区分每个客户的数据。
抱歉,答案很长。我花了一些时间才达到我的目的。
参考