web-dev-qa-db-ja.com

クライアントサーバーを作成するJavaアプリケーション

Javaアプリケーションをクライアント/サーバー方式で作成しようとしています。クライアントは、サーバーからのデータを表示するSWTのGUIです。サーバーはデータベースに接続されています。

申し訳ありませんが、これは確かに古典的な質問ですが、開始方法がわかりません。

私が働いていたプロジェクトでは、Glassfishサーバーを透過的に呼び出すためにProxy.newProxyInstance()を使用して多くの魔法を実装しました。

Glassfishサーバーを使用したくありません。プレーンJavaで単純なものが欲しいだけです。しかし、プロキシの概念はかなりクールなようです。

そのようなことのアイデアや例はありますか?クライアントの要求を処理するサーバー部分を作成するにはどうすればよいですか?

前もって感謝します

フルミニス

9
fluminis

TCPについて説明します。
基本的な概念は、マシン上で「サーバー」を実行する必要があるということです。そのサーバーは、接続を待機しているクライアントを受け入れます。各接続はポートを経由します(ご存知のとおり、私は願っています...)。
1025未満のポートはほとんどの場合標準プロトコル(HTTP(80)、FTP(21)、Telnetなど)用に予約されているため、常に1024を超えるポートを使用してください。

ただし、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:もちろん、すべてのネットワークコードは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。読み込まれた行()

このメソッドはバッファを使用せず、バイトごとに読み取り、改行をチェックします。したがって、このメソッドは、基になる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);
_

オブジェクトを取得したら、シリアル化を使用して接続の反対側に送信できます:ObjectOuputStreamsおよびObjectInputStreams。これらの2つのクラスを使用すると、ストリームを介してオブジェクトを読み書きできます。

_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.
_

_(***)_:reset()の詳細といつ使用するかについては、 私の質問 を確認してください。

38

Glassfishは必要以上に火力があるかもしれませんが、既存のライブラリを活用することを諦めません。

ソケットのいくつかのオプション:

ソケットよりもWebサービスを利用することにした場合は、 Jetty がフットプリントの小さいHTTPを利用する方法です。

単純なクライアントサーバータイプのプログラムを作成したい場合は、この チュートリアル に記載されているアドバイスに従うことができます。

もう少し複雑なことをしたい場合は、プレーンJavaと言うように、 [〜#〜] rmi [〜#〜] を見る必要があるかもしれません。 =。

ただし、最近では、 Webサービス が大流行しており、長期的にはより単純であることがわかる場合があります。

3
  1. 提供するサービスを特定します(loadThing、editThing、makeThingBelch)
  2. 通信/メッセージングプロトコルを決定します(httpは簡単に思えます)。
  3. サービスを実装し、それらが機能することを確認するために頻繁に単体テストを行います。
  4. 新しいサービスを追加したり、既存のサービスを変更したりする必要があるかもしれないことを念頭に置いて、今すぐクライアントの作成を開始してください。

頭に浮かぶことの1つは、既存のアプリケーションサーバーを使用するのではなく、なぜ「単純なJava」で記述したいのかということです。通信、セキュリティ、トランザクションの整合性などを抽象化して管理するためのEJB3のことは何ですか?

1
jaydel