2011-01-06 58 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應用的方法。

相關問題