- - PR -
ソケット通信について
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-11-09 01:58
お世話になっております。
ソケット通信を勉強しているのですが、なかなかうまくいきません。 16個のファイルの送信を行うと、2回に1回、エラーが出てしまう感じです。 送信側のソケット関係を疑い、やけくそになってclose()の処理をしてみましたが 改善されませんでした。 何かヒントをいただけると幸いです。 デバッグ出力:----------------------------------------------------- default.aviファイル送信開始 default.aviのファイルをストリームに書き出しました。 default.aviファイル送信開始 java.net.SocketException: Connection reset by peer: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(Unknown Source) at java.net.SocketOutputStream.write(Unknown Source) at MySendListener.actionPerformed(myListener.java:196) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) Source) 以下省略 長くて申し訳ありませんが、ソースを付属いたします。 送信側:----------------------------------------------------- public void actionPerformed(ActionEvent e){ for (int k=0;k< tx.file.length ;k++){ System.out.println(tx.file[k].getName()+"ファイル送信開始"); try{ socket = new Socket("localhost",20000); out = socket.getOutputStream(); fin = new FileInputStream(tx.file[k]); stack = new ByteArrayOutputStream(); byte b[] = new byte[255]; int len = -1; while((len=fin.read(b,0,b.length))!=-1){ stack.write(b,0,len); } stack.flush(); byte buf2[] = stack.toByteArray(); out.write(buf2, 0, buf2.length); out.flush(); out.close(); fin.close(); stack.close(); socket.close(); System.out.println(tx.file[k].getName()+"のファイルをストリームに書き出しました。"); }catch(Exception fe){ fe.printStackTrace(); }finally{ try{ fin=null; out=null; out=null; stack = null; socket=null; if(fin != null){fin.close();System.out.println("finが閉じていませんでした");} if(out != null){out.close();System.out.println("outが閉じていませんでした");} if(stack != null){stack.close();System.out.println("stackが閉じていませんでした");} if(socket != null){ socket.close();System.out.println("socketが閉じていませんでした");} }catch(Exception fe){ fe.printStackTrace(); } } } } 受信側:----------------------------------------------------- public static void main(String[] args) { recive rc = new recive(); for(int i=0;i<16;i++){ try{ serversocket = new ServerSocket(20000); System.out.println("リクエスト待ち"); socket = serversocket.accept(); System.out.println("リクエストがありました"); in = socket.getInputStream(); fout = new FileOutputStream("D://test"+i+".avi"); stack = new ByteArrayOutputStream(); byte b[] = new byte[255]; int len = -1; while((len= in.read(b,0,b.length))!=-1){ stack.write(b,0,len); } stack.flush(); byte buf2[] = stack.toByteArray(); fout.write(buf2, 0, buf2.length); fout.flush(); fout.close(); stack.close(); socket.close(); serversocket.close(); System.out.println("ストリームをファイルに書き出しました。"); fout.close(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ in=null; fout=null; stack=null; socket=null; serversocket=null; if(in != null){fout.close();System.out.println("foutが閉じていませんでした");} if(fout != null){fout.close();System.out.println("foutが閉じていませんでした");} if(stack != null){stack.close();System.out.println("stacktが閉じていませんでした");} if(socket != null){socket.close();System.out.println("socketが閉じていませんでした");} if(serversocket != null){ serversocket.close();System.out.println("serversocketが閉じていませんでした");} }catch(Exception fe){ fe.printStackTrace(); } } } } ByteArrayに読み込む部分などはまるまる こちらを参考にさせていただきました。 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=18864&forum=12 | ||||
|
投稿日時: 2005-11-09 02:21
パッとみただけでもかなりツッコミどころ満載なので、まずはもっとシンプルなサンプルコードを参照してみたほうがいいでしょう。
ちょっと検索してみたら以下のようなサイトがありました。 http://ysserve.int-univ.com/sugsi/Lecture/java/L5/05-03-02.html クライアント側はわざわざ一度ByteArrayOutputStreamに書き出していますが、何故直接 SocketのOutputStreamに書き出さないのでしょう? | ||||
|
投稿日時: 2005-11-09 02:38
> stack.write(b,0,len);
これは、送信用ソケットに書かんとスタックに書くもんなんかね!? よう知らんのですが(笑) | ||||
|
投稿日時: 2005-11-09 03:02
mogeさん、早速の返信ありがとうございます。 実は最初は、下記のようなもっとシンプルなコードで書き出しを行ってみたのです。 この場合、見た目上ファイルの転送ができ、クライアントとサーバーで ファイルサイズも一致していたのですが、実際にファイルを開くと、 破損ファイルになっていて読めなかったのです。 OutputStreamについて勉強不足で申し訳ないのですが、書き出しの際に 余計なバイトデータが含まれて(そんなことないか・・・)破損が 起きたのかな?と考え、過去ログを参考に一度ByteArrayに蓄積をしてみたということです。 ご提示いただいた先を参考に、もう一度作成してみようと思います。 最初のクライアント: try{ FileInputStream fi = new FileInputStream(rm1.filename); Socket so = new Socket(HOST,PORT); OutputStreamWriter os = new OutputStreamWriter(so.getOutputStream()); //DataOutputStream os = new DataOutputStream(new BufferedOutputStream((so.getOutputStream()))); int i; while((i = fi.read())!=-1){ os.write(i); } os.close(); fi.close(); so.close(); }catch(Exception se){ rm1.lb2.setText("サーバー側が開始されていません"); se.printStackTrace(); } 最初のサーバ: try{ int i; FileOutputStream fos = new FileOutputStream(ss2.filename); ServerSocket server = new ServerSocket(PORT); //while (true){ Socket ss = server.accept(); InputStreamReader in = new InputStreamReader(ss.getInputStream()); //DataInputStream in = new DataInputStream(new BufferedInputStream((ss.getInputStream()))); while((i = in.read())!=-1){ fos.write(i); } //} fos.close(); in.close(); ss.close(); server.close(); }catch(Exception e){ System.out.println("サーバーを終了します"); ss2.lb2.setText("有効なファイル名を指定してください"); e.printStackTrace(); } | ||||
|
投稿日時: 2005-11-09 03:10
最初のコードのほうがはるかに正解に近そうですね。
転送しようとしているファイルはバイナリファイルですか? そうであれば書き出し時にOutputStreamWriterをかませているのが原因ではないでしょうか? Writer系はテキストファイル専用なので素直にそのままOutputStreamを使えば問題ないと思いますがどうでしょう? | ||||
|
投稿日時: 2005-11-09 04:11
moge様、ご指摘の通り、OutputStreamとInputStreamをそのまま使ったら転送に成功しました! //送信側(改善後) OutputStream os = so.getOutputStream(); //受信側(改善後) InputStream in = ss.getInputStream(); OutputStreamは抽象クラス、抽象クラスは上記のように参照せずに他のクラスで 必ずラップ(?)すると思い込んで、Writer系のクラスをうっかり使ってしまいました。 本当にありがとうございます。 あと、関連した質問なのですが、クライアント側のファイル名と拡張子をサーバー側 に渡したいと思い、FileクラスをシリアライズしてObjectOutputStreamでサーバーに 渡すという方法をとってみたのですが、他にも簡便な方法はありますでしょうか? 初歩的な質問ばかりですみません。 [ メッセージ編集済み 編集者: もの 編集日時 2005-11-09 04:30 ] | ||||
|
投稿日時: 2005-11-09 09:51
Fileのインスタンスを送るのは簡単ですが「やりすぎ」って気がしますね。どうせ送るならStringインスタンスでじゅうぶんではないでしょうか。
自分だったら、Javaに依存するのも嫌なので、
などのようにフォーマットを決めて、それを送受信するようにします。 |
1