JavaでのSocketプログラミング(2)-向上

4633 ワード

[size=medium]
[b]毎日行って、千里を恐れない.しょっちゅうやっているので,千万のことを恐れない.[/b]
毎日歩いていれば、千里を歩いても怖くないし、毎日仕事をしていれば、何事も怖くないという意味です.勉強も同じで、毎日少し勉強すれば、千万の知識を学ぶことを恐れない.
前回はSocketプログラミングについて初歩的な理解を得ましたが、今日は勉強を続けましょう.前回は簡単なサービス側とクライアントプログラムを書きましたが、クライアントの書き込み、サービス側の読み取りを実現しました.今日は、サービス側とクライアントが同時に読み書きするプログラムを実現します.
[b]ニーズ:サービス側とクライアントの同時読み書きを実現する.[/b]
皆さんの理解を容易にするために、私はプログラムフローチャートを描きました.専門的ではありませんが、美観的ではありませんが、問題を説明することを目的としています.
[b]1、プログラムフローチャート:[/b]
[img]http://dl2.iteye.com/upload/attachment/0095/9910/64ca9221-8c77-35b7-92fc-cad0b36523e3.jpg[/img]
[b]2、コード実装:[/b]
[b]1)サービス側コード:[/b]
[/size]

/**
*
* :
* @author Sam
*
*/
public class EnhanceServer {

/**
* @param args
*/
public static void main(String[] args) {
try {
// ServerSocket,
ServerSocket ss = new ServerSocket(9999);
System.out.println("Server ...");
//
Socket socket = ss.accept();
// ,
InputStream is = socket.getInputStream();

byte[] buffer = new byte[1024];
int len = 0;
// ,
StringBuilder sBuilder = new StringBuilder();
int index;
while ( (len=is.read(buffer)) != -1 ) {
String temp = new String(buffer, 0, len);
// ,
if ( (index=temp.indexOf("eof")) != -1 ) {
//
sBuilder.append(temp.substring(0, index));
break;
}
// , ,
sBuilder.append(temp);
}
System.out.println("Server : " + sBuilder.toString());

// ,
OutputStream out = socket.getOutputStream();
out.write("Hello Client!".getBytes());
out.write("eof".getBytes());//
out.flush();

out.close();
is.close();
socket.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

[size=medium]
[b]サービス側コード分析:[/b]
[b]1)コードフロー:[/b]サービス側はクライアントから送信されたデータを読み出し、コンソールに出力し、読み終わったらクライアントに応答データを書きます.
前述したように、サービス側がクライアント要求を傍受する際に使用するacceptメソッドはブロックメソッドである.
[b]2)問題の原因:[/b]ここでwhileループ判定条件におけるreadメソッドもブロック式に動作している.つまりwhileループ判定条件ではデータが読み込まれるとループ体が実行され、そうでなければずっとブロック状態になり、その後のコードは永遠に実行されない.
[b]3)ソリューション:[/b]したがって、通常、クライアントから送信されたデータに終了フラグが含まれていると、サービス側はループを飛び出し、次のコードを実行する終了フラグを約束します.
ここでは終了マークをeofと約束し、データを書くたびに終了マークを書きます!
[b]2)クライアントコード:[/b]
[/size]

/**
*
* @author Sam
*
*/
public class EnhanceClient {

/**
* @param args
*/
public static void main(String[] args) {
try {
// ( , )
Socket socket = new Socket("127.0.0.1", 9999);
// ,
OutputStream out = socket.getOutputStream();
//
out.write("Hello Server!".getBytes());
out.write("eof".getBytes());// ,
out.flush();

// ,
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
// StringBuilder
StringBuilder sBuilder = new StringBuilder();
int index;
while ( (len=is.read(buffer)) != -1 ) {
String temp = new String(buffer, 0, len);
// ,
if ( (index=temp.indexOf("eof")) != -1) {
sBuilder.append(temp.substring(0, index));
break;
}
sBuilder.append(temp);
}
System.out.println("Client : " + sBuilder.toString());
out.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

[size=medium]
[b]クライアントコード解析:[/b]
1)[b]コードフロー:[/b]
クライアントは、サービス側にデータを書き込み、書き終わった後、サービス側から返された応答データを読み出し、コンソールに出力します.
[b]問題の原因:[/b]
同様に、クライアントがデータを送信した後、ストリームに終了フラグを書いて、サービス側のデータが送信されたことを通知します.
[b]3、運転結果:[/b]
注意:Clientプログラムを実行する前に、サーバプログラムを実行します.結果は次のとおりです.
[b]1)サーバプログラムコンソール:[/b]
[img]http://dl2.iteye.com/upload/attachment/0095/9933/0f9e59ac-4cf6-313f-8f6e-74d59f160ac7.jpg[/img]
[b]Clientプログラムコンソール:[/b]
[img]http://dl2.iteye.com/upload/attachment/0095/9935/739f9e69-4ec3-394d-afef-d8ebcc6329dc.jpg[/img]
[b]4、まとめ:[/b]
これがサービス側とクライアントが同時に通信するプログラムです.クライアントはサービス側にデータを送信し、サービス側はデータを受信した後、対応する結果をクライアントに返します.
[/size]