【问题标题】:make a client server java application制作客户端服务器java应用程序
【发布时间】:2011-01-06 14:28:49
【问题描述】:

我正在尝试以客户端/服务器方式制作 Java 应用程序。 客户端是 SWT 中的一个 GUI,它显示来自服务器的数据。服务器已连接到数据库。

好的,抱歉,我敢肯定这是一个经典问题,但我不知道如何开始。

在我为他们工作的一个项目中,他们使用 Proxy.newProxyInstance() 实现了很多魔法来透明地调用 Glassfish 服务器。

我不想使用 Glassfish 服务器。我只想要简单的Java。但是代理的概念似乎很酷。

你有这样的想法或例子吗?如何编写服务器部分来处理客户端的请求?

提前致谢

弗鲁米斯

【问题讨论】:

  • 我打算建议尝试 JMS 生产者/消费者方法,但你想要一些简单的东西。

标签: java client-server


【解决方案1】:

我将解释 TCP:
基本概念是您必须在机器上运行“服务器”。该服务器接受等待连接的客户端。每个连接都通过一个端口(你知道,我希望...)。
始终使用高于 1024 的端口,因为低于 1025 的端口大部分时间都保留给标准协议(如 HTTP (80)、FTP (21)、Telnet 等)

然而,在 Java 中创建服务器是通过这种方式完成的:

ServerSocket server = new ServerSocket(8888); // 8888 is the port the server will listen on.

如果您想进行研究,“Socket”是您可能正在寻找的词。
并且要将您的客户端连接到服务器,您必须编写以下代码:

Socket connectionToTheServer = new Socket("localhost", 8888); // First param: server-address, Second: the port

但是现在,仍然没有连接。服务器必须接受等待的客户端(正如我在上面注意到的):

Socket connectionToTheClient = server.accept();

完成!您的连接已建立!通信就像 File-IO。您唯一需要记住的是,您必须决定何时刷新缓冲区并真正通过套接字发送数据。
使用 PrintStream 进行文本编写非常方便:

OutputStream out = yourSocketHere.getOutputStream();
PrintStream ps = new PrintStream(out, true); // Second param: auto-flush on write = true
ps.println("Hello, Other side of the connection!");
// Now, you don't have to flush it, because of the auto-flush flag we turned on.

用于文本阅读的 BufferedReader 是不错的(最佳*)选项:

InputStream in = yourSocketHere.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = br.readLine();
System.out.println(line); // Prints "Hello, Other side of the connection!", in this example (if this would be the other side of the connection.

希望您可以从这些信息开始建立网络!
PS:当然,所有网络代码都必须尝试捕获 IOExceptions。

编辑:我忘了写为什么它并不总是最好的选择。 BufferedReader 使用缓冲区并尽可能多地读取缓冲区。但有时您不希望 BufferedReader 窃取换行符后的字节并将它们放入自己的缓冲区中。
简短的例子:

InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
// The other side says hello:
String text = br.readLine();
// For whatever reason, you want to read one single byte from the stream,
// That single byte, just after the newline:
byte b = (byte) in.read();

但是 BufferedReader 在他的缓冲区中已经有了你想要读取的那个字节。因此调用in.read() 将返回读取器缓冲区中最后一个字节之后的字节。

因此,在这种情况下,最好的解决方案是使用DataInputStream 并以自己的方式管理它,以了解字符串的长度,并仅读取该字节数并将它们转换为字符串。或者:你使用

DataInputStream.readLine()

此方法不使用缓冲区并逐字节读取并检查换行符。所以这个方法不会从底层 InputStream 窃取字节。


编辑:您可以开发自己的协议,在该协议中您可以使用 Java Reflexion 请求方法调用。例如:

String className = ...;
String methodName = ...;
Class[] methodParamTypes = ...;
Object[] methodParams = ...;
Class cl = Class.forName(className);
Method me = cl.getDelcaredMethod(methodName, methodParamTypes);
Object returnValue = me.invoke(this, methodParams);

获得对象后,您可以使用序列化将其发送到连接的另一端:ObjectOuputStreamsObjectInputStreams。使用这两个类,您可以通过流写入和读取对象。

Object obj = ...; // Your object you want to write through the stream. (Needs to implement java.io.Serializable)
ObjectOutputStream oos = new ObjectOuptputStream(socket.getOutputStream());
oos.writeObject(oos);
oos.reset(); // (***)
// Don't close it! Otherwise the connection will be closed as well.

在连接的另一端:

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Object object = ois.readObject(); // Read the object
// Don't close it!
// Then cast it to whatever you want.

(***):查看my question 了解有关reset() 以及何时使用它的更多信息。

【讨论】:

  • 感谢您的回答。我很了解您的示例如何检索文本。但是 soket 是否可以调用服务器上的方法并获得复杂的对象作为回报?
  • 看看 ObjectOutputStream 和 ObjectInputStream。
  • 另外,您可能正在考虑 java RMI(远程方法调用) - 上面有很好的文档。
  • 注意:unix 要求你是 root 才能使用
  • @ThorbjørnRavnAndersen:这是我在回答中提到的第一件事。
【解决方案2】:

Glassfish 的火力可能超出您的需求,但我不会放弃利用现有库。

套接字的一些选项:

如果您决定更多地使用 Web 服务而不是套接字,Jetty 是使用小型 HTTP 的方式。

【讨论】:

    【解决方案3】:

    如果您想编写一个简单的客户端服务器类型程序,您可以按照tutorial 中给出的建议进行操作。

    如果您想做一些更复杂的事情,如您所说,使用纯 Java,那么您可能需要查看 RMI

    然而,这些天来,web services 风靡一时,您可能会发现从长远来看它更简单。

    【讨论】:

      【解决方案4】:
      1. 确定您要提供的服务(loadThing、editThing、makeThingBelch)
      2. 决定通信/消息传递协议(http 似乎很简单。)
      3. 实施服务,经常进行单元测试以确保它们正常工作。
      4. 现在开始编写客户端,记住您可能需要添加新服务或更改现有服务。

      想到的一件事是,为什么要使用“简单的 java”而不是使用现有的应用程序服务器来编写它?一些 EJB3 东西来抽象和管理通信、安全性、事务完整性等?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-16
        • 1970-01-01
        • 1970-01-01
        • 2020-09-21
        相关资源
        最近更新 更多