2011-01-06 56 views
9

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

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

在我工作的一个项目中,他们实现了大量的神奇功能,用Proxy.newProxyInstance()来透明地调用Glassfish服务器。

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

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

在此先感谢

Fluminis

+0

我打算建议尝试JMS生产者/消费者方法,但你想要一些简单的东西。 – 2011-01-06 14:38:39

回答

34

我打算解释TCP:
基本概念是,你必须在机器上运行“服务器”。该服务器接受等待连接的客户端。每个连接都通过一个端口(你知道,我希望...)。
始终使用端口1024以上的,因为端口比1025低最的标准协议保留的时间(如HTTP(80),FTP(21),远程登录,...)

但是,创建Java中的一个服务器这样做:

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

“套接字”是你可能寻找的词,如果你想做研究。
和你的客户端连接到你有写这个服务器:

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:当然,所有网络代码都必须尝试处理IOException。

编辑:我忘了写它为什么不总是最好的选择。 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()以及何时使用它。

+0

谢谢你的回答。我很了解你如何修改文字。但是,soket可以在服务器上调用一个方法并获得复杂的对象吗? – fluminis 2011-01-06 15:56:40

+0

看看ObjectOutputStream和ObjectInputStream。 – 2012-04-21 13:07:14

+1

另外,你可能会考虑java RMI(远程方法调用) - 这里有很好的文档。 – 2013-02-01 16:10:07

3

如果你想编写一个简单的客户端服务器类型的节目,你可以按照这个tutorial给出的建议。

如果你想做一些更多的事情,就像你说的那样使用普通的Java,那么你可能需要看看RMI

然而,这些天,web services都是愤怒,你可能会发现,从长远来看它更简单。

1
  1. 标识要提供(loadThing,editThing,makeThingBelch)
  2. 决定在通信/通讯协议的服务(HTTP似乎straightfoward。)
  3. 实现服务,单元测试经常以确保他们的工作。
  4. 现在开始写客户端,记住您可能需要添加新服务或更改现有服务。

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

5

玻璃鱼可能比你需要更多的火力,但我不会放弃利用现有的图书馆。

对于插座的一些选项:

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

相关问题