- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在做一个小的客户端/服务器应用程序。目前它运行良好,但我需要添加一个“选项”。
服务器类是这样的:
public class Server {
public static void main(String[] zero) throws IOException {
ServerSocket serverSocket ;
Socket clientSocket ;
DataBase DB = new DataBase();
System.out.println("ouverture du server");
serverSocket = new ServerSocket(2000);
DB.printAll(); //just to see the DB.
while(true) {
try {
clientSocket = serverSocket.accept();
Thread t = new Thread(new Connect(clientSocket, DB));
t.start();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
因此很多客户端都能够连接到服务器。我的观点是:我希望连接的客户端(例如 Client1)能够向他选择的另一个连接的客户端(Client2)发送某些内容。
我的问题是:既然所有客户端都通过不同线程中的 clientSocket 连接到服务器,那么 Client1 如何找到/拥有/检索 Client2 的套接字?
我已阅读 this它建议创建一个包含每个连接客户端的输出流的数据输出流列表。这似乎是一个好主意,但我更愿意对套接字执行相同的操作(因为我不确定现在是否需要“数据”输出流或另一个输出流,并且在任何情况下它都会对于我来说,套接字更清楚)。
另外,Client2 正在与服务器做他自己的事情,其中包括交换数据,因此他将使用他的输出/输入流。我必须确保这不会混淆。
例如,假设 Client2 向服务器发送一些内容并等待响应。然后Client1向Client2发送一些东西; Client2 接收 Client1 发送的内容,而不是服务器响应;因为他不应该收到这个,这会导致 fatal error 。
我读过一些关于同步线程的内容,这似乎是我所需要的,但我是java新手,这有点难?
我想如果我将Client2 Socket声明为synchronized,那么线程将等到clientSocket空闲后再使用它;并且由于客户端不应该断开连接(如果他断开连接,那么套接字已关闭,因此我们无法向他发送任何内容),(client1 的)线程将无法使用 client2 的套接字。
现在,如果我同步DataOutputStream,有时client2和服务器之间的通信涉及许多不同的输出流,因此DataOutputStream可以自由使用,但Client2仍然会等待来自服务器的输入,而不是来自Client1的输入,所以不会相同的输入。
也许我可以直接同步完整的OutputStream。或者也许我说的话没有任何意义。帮忙?
最佳答案
好吧,既然我发布了它,我想我也可以问它。
所以,这不是一个完美的解决方案(在我看来),我还没有完全完成它,但到目前为止它似乎有效。
对于第一个问题(如何检索另一个客户端套接字),我在服务器端创建一个静态哈希表,以客户端名称作为键,以套接字作为值。每当客户端连接时,他就会被添加到此表中;当他断开连接时,他被删除了(我没有尝试断开连接部分)
private static Hashtable<String,Socket> connectedClients= new Hashtable<String, Socket>();
public static void setConnectedClient(String username, Socket clientSocket) {
connectedClients.put(username, clientSocket);
}
public static void disconnectClient(String user) {
connectedClients.remove(user);
}
因此,无论我在服务器端的程序中,我都可以检索客户端套接字(知道他的用户名)。
对于第二个问题(如何避免与其他客户端与服务器的工作混淆),我正在创建第二个套接字。这意味着,在客户端有两个套接字:一个用于与服务器通信,一个用于与另一个端口上的客户端(来自服务器)通信。这意味着我在服务器端还有另一个服务器套接字用于另一个端口。因此,当客户端连接到服务器时,会在客户端和服务器端创建第二个套接字。
Socket TCHATSocket = Server.getServerSocket().accept(); //create a new socket specifically for TCHAT
Server.setConnectedClient(user, TCHATSocket); //register the client ID & TchatSocket in the list of connected clients.
现在,在客户端,我必须继续监听来自此套接字的任何输入(以防另一个客户端想通过服务器与我通信),但当我与服务器进行操作时则不能。
为此,我在客户端创建另一个线程。当客户端连接时,它启动创建第二个套接字的线程并等待来自服务器的输入。但是,当客户端启动任何涉及与服务器通信的函数时,该线程将暂停,然后在函数结束时取消暂停。这是线程类:
package client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class TCHAT extends Thread{
private InputStream in;
private OutputStream out;
private Socket pakeSocket;
private String message;
private volatile boolean pause = false;
public void pause() {
pause = true;
}
public void unPause() {
pause = false;
synchronized(this) {
notify();
}
}
public TCHAT() {
try {
tchatSocket = new Socket(InetAddress.getLocalHost(),2004);
in = tchatSocket.getInputStream();
out = tchatSocket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run(){
while(!tchatSocket.isClosed()) {
if(pause) {
System.out.println("TCHAT paused");
synchronized (this) {
try {
wait();// wait until someone calls notify() (by calling the method unPause)
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
else {
System.out.println("Waiting for TCHAT demand");
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
message = br.readLine();
System.out.println(message);
//Find a way to blok the while after receiving the message:
tchatSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
正如你所看到的,它并没有真正终止:现在我只是从服务器收到一条消息,然后关闭套接字;但我想你可以在关闭它之前做任何你想做的事情。另外,由于某种原因,当我调用暂停()时,我从未收到“TCHAT已暂停”消息,并且当我取消暂停时,我没有收到另一个“等待TCHAT需求”,但它似乎有效(因为没有暂停其他客户端功能无法工作,但在这里它们工作良好,并且即使在上传或其他操作之后,客户端也可以正确接收来自服务器的消息。)
基本上,当我想使用客户端功能时,我只需这样做:
TCHAT.pause();
upload(file); //or any function involving client/server communication
TCHAT.unpause();
希望它能帮助别人,但仍然很高兴让它发挥作用:)
关于Java 客户端 - 服务器 - 具有同步线程的客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51650024/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!