【问题标题】:How to get a socket object without a reference variable?如何获取没有引用变量的套接字对象?
【发布时间】:2013-05-05 02:01:25
【问题描述】:

我整天都在考虑这个问题,我真的不认为标题是否正确,但在这里,让我解释一下我的情况:我正在做一个项目,一个用 Java 制造的服务器,供客户使用德尔福。连接很好,多个客户端都有自己的线程,I/O 工作良好。客户端将字符串发送到我使用 BufferedReader 读取的服务器。根据服务器接收到的保留字,它会做出一个动作。在客户端发送字符串之前,它会将信息插入到 SQL Server 数据库中,以便服务器在通过套接字获取命令/命令后进行检查。服务器获取数据库中的信息,对其进行处理,然后将其发送到……我们称之为“黑暗面”。

在交易完成并且信息被发送到黑暗方的那一刻,服务器将信息插入......咳咳,黑暗信息到数据库表中,以便客户端可以去获取它请求的内容。但是,我需要向客户报告! (“哟,再次检查数据库兄弟,你想要什么:3”)。

连接,套接字是在其他类中制作的。不是我想用来回答客户端的那个,所以如果我没有套接字,我就没有输出流,我需要回复。那个类,一个处理并向黑暗面发送信息的类,将处理数百个分组事务。

我的问题在这里:我无法向已完成的客户端报告,因为我没有该类中的套接字引用。我将客户端线程实例化为:

new Client(socket).start(); 

没有引用变量的对象,但是,我可以选择:在建立新连接时将套接字及其 ip 存储在 HashMap 对象中,如下所示:

sockets.put(newSocket.getInetAddress().getHostAddress(), newSocket);

然后我可以得到套接字(这样我就可以得到输出流和应答)调用这样的静态方法:

 public static Socket getSocket(String IP) {

        Socket RequestedSocket;
        RequestedSocket = sockets.get(IP);

        return RequestedSocket;
    }

但我希望您告诉我是否有更好的方法来执行此操作,比将所有这些套接字存储在列表/哈希图中更好。如何在没有引用变量的情况下获取这些对象?或者也许这是一个很好的方法,我只是想超越限制。

P.S.:我尝试将 Client 对象存储在数据库中,并对其进行序列化,但套接字无法序列化。

谢谢。

【问题讨论】:

  • 是什么阻止你在 Client 类中保留引用?
  • 客户端类中有一个引用,(new Client()),但我没有客户端类的所有引用。感谢您的回答
  • 我建议您以某种方式跟踪您的客户端,而不是套接字,然后在 Client 类中添加一个方法来通知客户端,例如 Client#notify("data is available")
  • 您说您无法控制客户端代码,但您希望获得有关如何更改流程的建议,以便他们知道他们的工作已完成并获取结果。如果客户端不更改代码,您将如何在服务器中进行更改?
  • 我真正想要的是一种方式来告诉他们他们的工作已经完成,通过 Socket,我的意思是,只是消息。使用 hashmap 我可以做到,但我只是想看看人们是否有更好的方法。但是我会关闭连接并将哈希图中的位置设置为 Null,所以垃圾收集器会做其他工作

标签: java sockets serversocket


【解决方案1】:

这是您的设计问题。您需要在某处跟踪它们,一种解决方案可能是简单地创建一个单例类 [SocketMapManager] 例如保存哈希图,以便您可以从其他类静态访问它。 http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html

【讨论】:

  • 如果这些套接字连接在不确定的时间内保持打开状态,您认为它们会发生什么?你认为单例是一个保持连接的地方还是一个骗子池?你有这方面的经验(套接字和开放流)吗?
【解决方案2】:

任何告诉您保留对套接字/连接/流的引用的解决方案都是错误的 -> 因为这意味着您的连接将在服务器工作时被阻止。

您有几个选项可供选择 1.让客户端也充当服务器。当他们连接时,他们向服务器提供他们的 IP、端口和一些秘密字符串作为握手的一部分。这意味着您可以控制客户端代码来实现这一点。

  1. 服务器具有接受新作业或检查旧作业状态的协议。客户端定期池化服务器。

  2. 客户端连接到数据库或连接到数据库以获取作业状态的其他应用程序(Web 服务或普通套接字,如原始应用程序)。意思是服务器给客户端一个作业ID。

一个套接字打开,然后它打开一个操作系统资源。可以阅读Network Programming: to maintain sockets or not?

一切都取决于 1. 一次/5 分钟内连接多少个客户端。 2. 处理一个客户的请求需要多少秒/分钟

如果 5 分钟内的客户端数量最多(在接下来的 3 年内)每次 300 个/任何 5 分钟的持续时间,并且每个请求最多需要 50 秒来处理,那么具有最多 50,000 个套接字的专用服务器就足够了。否则,您需要异步或更多服务器(以及 DNS/Web 服务器/端口转发或其他负载平衡方法)

【讨论】:

  • 感谢您的回答。我喜欢这样做的方式,这样会非常好,客户端自行运行,检查交易是否完成,存储 id 或 IP。但是,我忘了说我无法控制客户端代码。
  • 为什么保留引用会阻止连接?请解释一下。
  • 因为您提出了一个可疑的声明,已被查询,但您没有备份。
  • 我将如何备份它?如果其他一些线程/进程保持套接字打开,它们会阻塞。您是否看到指向stackoverflow.com/questions/519850/… 的已编辑答案
  • 您可以通过做出合理的陈述来支持它。你没有。保持套接字打开与保持对它的引用不同,它们都不会导致任何“阻塞”。导致事情“堵塞”的原因是阻塞 I/O。 您引用的问题中的答案主要是支持保持套接字打开,并且那里什么都没有关于“堵塞”。您的主张仍然不受支持:如果我可以再次投反对票,我会这样做。
【解决方案3】:

我在试图了解什么是操作流程以及您究竟有什么处置时遇到了一些问题。这个顺序正确吗?
1. 客户端写入数据库 (delphi)
2. 客户端写入服务器 (delphi)
3. 服务器写入数据库 (java)
4. 服务器写入客户端 (java)
5.客户端读取数据库(delphi)
问题是通过 4 吗?

更重要的是:您是说Client 类中没有套接字,并且您也没有Client 的列表?
您是否可以使用反射从Client 搜索/获取套接字引用?
如果你说你没有套接字,你怎么能在HashMap中添加那个套接字呢?
最后但同样重要的是:为什么需要存储套接字?也许每个客户端都会打开一个用于多个请求的连接?

如果所有答案都可以传送到一个 ip:port 上,那就太好了……

【讨论】:

  • 顺序是对的。我说“我没有插座”,但我的意思是在将用于回答的课程中。因为我在没有标识符的情况下创建了每个线程,所以套接字是无法访问的,至少我创建了一个 HashMap 或它们的列表。我可以获取客户端的 IP 和端口,但据我所知:客户端套接字的 IP 和端口不足以在 Java 中发送/接收数据,我希望我错了。
  • 但是如果你用socket初始化Client,你就不能使用一个带有socketClient的结构的链表吗?这样你就可以同时拥有它们。您甚至可以通过套接字的hashCode() 对其进行排序,这样它会更快......如果您必须使用套接字手动回答客户端,Client 类在用它做什么?
猜你喜欢
  • 2021-08-04
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
相关资源
最近更新 更多