- PR -

ソケットの送信処理でフリーズ

投稿者投稿内容
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2006-09-04 19:44
お世話になります。

ソケット(TCP)通信を行うプログラムの送信処理で、プログラムが停止してしまいます。

処理は「Listen→Accept→受信→応答送信→相手切断を待つ→切断」を繰り返し行うという内容です。

毎回発生するわけではなく、何日間か稼動させていると発生します。

原因がまったく分からず困っています。
みなさんのお力お借りしたいです。

OSはLinuxです。
Javaのバージョンは、1.4.1_02です。

よろしくお願いします。

//-----------------------------------------------------------------------------------------------
public abstract class SocketBase{

private ServerSocket m_srvSock = null;
private Socket m_clntSock = null;

private InputStream m_sockIn = null; //入力用ストリーム
private OutputStream m_sockOut = null; //出力用ストリーム

public void listenSock(int iPortNo) throws Exception{
m_srvSock = new ServerSocket(iPortNo);
m_srvSock.setSoTimeout(3000);
}

public void acceptSock(int iTimeOut) throws Exception{
m_clntSock = m_srvSock.accept();
m_srvSock.close(); // サーバソケットをクローズ
m_clntSock.setSoTimeout(iTimeOut);
m_sockIn = m_clntSock.getInputStream();
m_sockOut = m_clntSock.getOutputStream();
}

public void receiveSock(String encode){
int rcvsize = 0;//受信Byte数
try {
rcvsize = m_sockIn.read(readbuf);
}catch(Exception e){
}
}

public void sendSock(String cmd, String encode){
try {
//送信
m_sockOut.write(cmd.getBytes(encode));
m_sockOut.flush();
} catch (Exception e) {
}
}
}

public class ReceiveSock extends SocketBase implements Runnable{

public void run() {
// アプリケーション終了までループ
while(**){
// Listen
super.listenSock(ポート番号);
// Accept
super.acceptSock(3000);
// 切断されるまでループ
while(true){
super.receiveSock(m_encode);// 受信
if(**){ // 受信成功
super.sendSock("応答電文"); // ●●ここで止まってしまいます
}else{ // 切断された場合
break;
}
}
super.disconnect();// 切断
}
}
}
//-----------------------------------------------------------------------------------------------
うえだ
ベテラン
会議室デビュー日: 2006/01/21
投稿数: 52
投稿日時: 2006-09-04 21:17
多分デッドロックしているんでしょうね。95%くらいの確率。(ここもイイカゲン)

スレッドダンプして調べてみましょう。
スレッドダンプでググッたら@ITがヒットしますよ。
解説が長いので、ここでは省略しますが
それを見てわからなければ悩みましょう。
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2006-09-04 22:04
log4Jで良いと思うんですが、トレースログとか出力
した方がいいんのではないですかね。
あと、
コード:
 } catch (Exception e) { 


は、トラブルの情報を闇に葬るブラックホールになるの
ではないですかね。
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2006-09-05 07:55
うえださん、小僧さん ありがとうございます。

>小僧さん
小僧さんにご指摘いただいた点については、実際には対応しています。
ソースコードを提示する際に、読みにくくなるかと思い、割愛しました。
一言書いておけば良かったです。申し訳ないです。

>うえださん
スレッドダンプについて調べてみました。
今回の現象の調査にはとても有効な方法だと思いました。
参考になりました。ありがとうございます。

ただ、スレッドダンプは、実際に現象が発生した時に行うものだと思いますが、
今回の現象は発生頻度も低く、またタイミングもよめないため、
現象が発生するまで待つというのは難しいかもしれません・・・。

他になにか調査する方法はないでしょうか?

よろしくお願いします。
いっきゅう
大ベテラン
会議室デビュー日: 2004/04/04
投稿数: 153
お住まい・勤務地: 兵庫
投稿日時: 2006-09-05 08:24
JDKのバージョンアップはできないのでしょうか?
とりあえず別のバージョンを入れて動かして見るとか。

ちなみにSoket関連では以下のバグ報告があります。
http://java.sun.com/products/archive/j2se/1.4.1_07/ja/ReleaseNotes.html
4680160 :java.net.ServerSocket.implAccept で JVM がクラッシュする
4674826 :java.net.Socket のコンストラクタからセキュリティ例外がスローされる
99ri
大ベテラン
会議室デビュー日: 2006/09/09
投稿数: 129
投稿日時: 2006-09-10 22:02
なぜ受信後の送信処理に問題があると判断したか不明ですが
プログラムを実行しているサーバ側かクライアント側で
TCP/IPのパケットダンプととってみては?
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2006-09-11 13:44
いっきゅうさん ご返信ありがとうございます。

JDKの1.4.1_02と1.4.1_07のソースを見比べてみましたが、
PlainSocketImplクラスのclose()に変更が行われており、
非ブロッキング中の切断は、2段階で行われるようになっていました。
このあたりの変更は、ちょっとだけ今回の不具合と関係ありそうな気がもしますが、
確信が持てません。
でも、試してみる価値はありそうな気もします。

検討してみます。
ありがとうございます。
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2006-09-11 13:47
ご返信ありがとうございます。

送信処理に問題があると判明したのは、
super.sendSock()を呼び出す前と後に、ログを出力するようにしたところ、
呼び出す前のログは出力されていましたが、
呼出し後のログは出力されていませんでした。
このことから、送信処理で停止していると判断しました。

引用:

未記入さんの書き込み (2006-09-10 22:02) より:
プログラムを実行しているサーバ側かクライアント側で
TCP/IPのパケットダンプととってみては?



これは、ネットワーク的なトラブルを疑ってみろということでしょうか?

スキルアップ/キャリアアップ(JOB@IT)