我正在开发一个Java客户端/服务器聊天应用程序,允许局域网内的用户在他们之间聊天。
在服务器应用程序中,我有一个主类,每当客户端连接到服务器时,它都会创建一个不同的线程。所以,基本上,我会打开一个TCP连接,每个客户端都在一个单独的线程上运行。
我在发送消息时遇到问题。当用户向服务器发送新消息时,服务器必须找到与目标用户有连接的线程并将该消息发送给他。我该怎么做。我已经将每个线程与一个用户对象相关联,因此我需要执行类似findThreadByUser(user)的操作,并且在获得引用后,只需调用发送消息的方法。我该怎么做?
下面是实现Runnable的ConnectionHandler类的一部分。我想访问该类的特定实例,更具体地说,是它的末尾的方法< code > sendToClient(String message)(外部运行方法)。我尝试使用HashMap来存储用户和线程,但是我无法访问< code > sendToClient(String message)方法
public class ConnectionHandler implements Runnable {
protected Socket socket;
private ServerData serverData;
private User currentUser;
BufferedReader inFromClient;
PrintStream outToClient;
String clientSentence;
String peerIp;
String peerHostName;
public ConnectionHandler(Socket socketToHandle, ServerData serverData) {
socket = socketToHandle;
this.serverData = serverData;
inFromClient = null;
outToClient = null;
currentUser = null;
clientSentence = " ";
}
@Override
public void run() {
peerIp = socket.getInetAddress().getHostAddress();
peerHostName = socket.getInetAddress().getHostName();
try {
outToClient = new PrintStream(socket.getOutputStream(), true);
/* Create a reading stream to the socket */
inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException ex) {
Logger.getLogger(ConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Error creating buffered handles.");
}
System.out.println("Handling connection to client at " + peerIp + " --");
Runnable r1 = new Runnable() {
public void run() {
while (true) {
try {
/* Read client's message through the socket's input buffer */
clientSentence = inFromClient.readLine();
} catch (IOException e) {
System.out.println(socket.getInetAddress() + "-" + peerIp + " broke the connection.");
break;
}
/* Output to screen the message received by the client */
System.out.println("Message Received: " + clientSentence);
List<String> processedClientSentence = ClientMessageProcessor.process(clientSentence);
if (processedClientSentence.get(0).equals(new String("LOGIN"))) {
String result = ServerActions.login(peerIp, peerHostName, processedClientSentence.get(1), serverData);
if (result.equals("success")) {
currentUser = serverData.getUserByIP(peerIp);
outToClient.println("USERS \"" + ServerActions.getUsers(serverData) + "\"");
} else {
outToClient.println("ERROR \'" + result + "\'");
}
} else if (processedClientSentence.get(0).equals(new String("GETUSERS"))) {
outToClient.println("USERS \"" + ServerActions.getUsers(serverData) + "\"");
} else if (processedClientSentence.get(0).equals(new String("USERINFO"))) {
} else if (processedClientSentence.get(0).equals(new String("MESSAGE"))) {
ServerActions.sendMessage(currentUser/*.getUserName()*/, processedClientSentence.get(1), processedClientSentence.get(2), serverData);
} else if (processedClientSentence.get(0).equals(new String("LOGOUT"))) {
} else {
}
}
}
};
new Thread(r1).start();
}
public void sendToClient(String message) {
outToClient.println(message);
}
}
为什么不发送广播,让正确的客户端接受消息呢?
将客户端对象存储在 HashMap
中,用户名
(这将是唯一的)作为键,与之关联的线程作为值......”
问题内容: 如何编写一个在ES6中仅以最紧凑的方式仅包含很少的属性的函数? 我想出了使用解构+简化对象文字的解决方案,但是我不喜欢代码中重复的字段列表。 有没有更苗条的解决方案? 问题答案: 尽管不能避免重复字段列表,但这里有些苗条。它使用“参数解构”来避免需要该参数。 @EthanBrown的解决方案更为通用。这是它的更惯用的版本,它使用和计算的属性(部分): 如果我们要保留属性的属性(例如和和
问题内容: 如果知道与该线程关联的ID,该如何获取正在运行的线程的引用? 例如 问题答案: 您有2种方法可以做到。两者都很简单: 旧方法:获取您可以循环访问..getParent()的根线程组。并打电话 较新(但速度较慢)。 第一种方法有一个小问题,由于存在错误,ThreadGroup可能根本无法枚举任何东西。 第二个比较慢,但是有安全漏洞。
问题内容: 我一直都在看:声明的对象常量使某些键用引号引起来,而另一些则没有。jQuery 1.4.2中的示例: **用引号 将前两个属性键(和 ) 包裹 起来,而其他两个都不用引号引起来的意义是什么? 有什么区别吗? 我一直在摸索ECMAScript 5规范;我所能找到的只是[ 15.12.3节的注6,重点是我的 ]: 注6:一个对象呈现为左括号,后跟零个或多个属性,以逗号分隔,右括号封闭。 属
我必须得到如下输出: 这是我的密码。没有错误。它以PlusThread开始并打印第一行。然后它将释放锁。之后,MultiplyThread开始运行。它将打印所有行,而不是通知PlusThread。 这是我的输出:
我想将输入XML转换为输出XML。同样,使用xslt进行XML转换。 输入xml和支持xml文件位于本地路径中(仅限同一路径)。 XSl和saxon9。jar位于服务器路径中。 将在本地路径中创建输出xml(与输入xml路径相同)。 使用xslt2.0我可以得到一个输入的xml值,但不能得到支持的xml值(存在于本地) d:\测试 下面是我的xsl用于从supporting.xml获取值 有人能帮
谢谢你考虑我的问题,我认为这实际上是在问: 不太确定下面的代码会如何死锁。 其结构大致如下所示,有两个类: < li >具有同步方法的主类工作器 < li >具有类级别同步方法的util类 Worker的< code>run方法会死锁,使< code>doSomething()不同步可以避免死锁。 真实应用程序的线程转储显示: “Worker”线程被阻塞-正在等待监视器锁定-- 此处的“sched