• ベストアンサー

Socket通信の0バイト受信について

現在、仕事でソケット通信によるファイル転送処理をJavaで実装しています。 単体テスト、結合テストと転送先のサーバを変えて行っているうちに結合テスト用のサーバにファイル転送するタイミングで、0バイト受信をしてしまうことがわかりました。 (※サイズが小さいファイルに起きやすいのかもしれません。。。なぜ・・・) プログラム内容は単体、結合とも同様です。 サーバは両方ともSolaris8です。 両者ともWeblogicを使用しています。 最初はプログラムでソケットが開きっぱなしなのでは?と疑いを持って、確認していましたが、単体環境で成功しているのに、結合環境で失敗するのを見ていると、転送先のサーバの設定やWeblogicに問題があるのでは?と思っています。 いろいろ調べてみたところ、下記サイトでそれっぽいことが書かれていましたが、実際にどの環境をどう直せば良いのかまでは至りませんでしたので、同じような経験がおありでしたら、是非ともアドバイスを頂きたく、質問させて頂きました。 ■UNIXソケットプログラミング http://hp.vector.co.jp/authors/VA003991/kouza/senior/kouza_socket.html お手数ですが、回答お待ちしております。 よろしくお願いします。

  • Java
  • 回答数3
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • bgbg
  • ベストアンサー率53% (94/175)
回答No.1

> サイズが小さいファイルに起きやすいのかもしれません 送信側端末のOutputStreamをcloseする前にちゃんとflushしていますか? 0バイト受信対策としては、read(byte[] b) でinputStreamからデータを取得し、戻り値が0だったら通信の終了とみなせば良いのではないでしょうか。 提示されたURLのドキュメントにはそのようなことが書いてあります。 ただ、通信の遅延でストリームからデータが取れない場合もありますので、そこはうまく実装する必要があるでしょう。

lotter
質問者

お礼

TO:bgbg様 早速のご回答ありがとうございました。 OutputStreamの実装箇所を確認してみたところ、おっしゃる通りflushが実行されていませんでした。 その部分を修正し、動作確認を行いましたので、おそらくこれで解決するとは思いますが、なにぶんテスト環境では動作が再現できないもので、、、 一時はテスト環境のAPorDBサーバのメモリサイズが極端に小さいのではないかと思い、確認してもらいましたが、テスト環境でも本番環境でも大した差はなく、バッファのメモリサイズオーバーによる自動flushでテスト環境はうまくFTP転送されていた訳ではなさそうです・・・ あとはその環境による動作結果の差異がわかれば完璧だと思うのですが。。。 とりあえず、flushは実装したので、ひと安心しております。 テスト環境での再現ができない件にて、何かアドバイスがありましたら、ご回答よろしくお願いします。 flushの件、本当に助かりました。 ありがとうございます。

lotter
質問者

補足

引き続き、不具合の調査を行っております。 bgbgさんのおっしゃる通り、プログラム的におかしい箇所は修正し、 動作確認を行いました。しかし、同不具合がいまだ発生しており、開発環境では発生せず、本番環境で発生することからネットワークの設定もおかしいのではないかと疑っています。 ソケット通信で検索して、下記URLにソケットバッファの設定が記述されていたので、その辺りも関係してくるのではないかと思っています。 現在はサーバ管理者にその旨を指摘し、調査を行ってもらっていますが、なにぶんこういったケースは初めてなもので、皆様の経験談をアドバイス下されば心強いと思っております。 ちなみに失敗するケースとして現時点でわかっていることは、 ・432バイトのFTP転送では失敗し、852バイトのFTP転送は成功。 ・テスト環境下での検証では上記不具合は再現せず。 ・テスト環境、本番環境ともに使用OS、バージョンは同じ。 となっております。 何卒、アドバイスありましたら、宜しくお願い致します。 ■ソケットバッファについて http://www.nal.ics.es.osaka-u.ac.jp/~t-tugawa/note/linux/sockbuf.html ※bgbg様、貴重なご意見でしたので、ポイントは後日発行させて頂きます。

その他の回答 (2)

  • guccii
  • ベストアンサー率31% (14/44)
回答No.3

javaでソケットI/Oを詳しく調べていないので、一概にはいえませんが、 ネットワークプログラミングの常識的な考えからいうと、ネットワークなのでこれぐらいの状況は普通のことだと思います。ネットワークプログラミングでは、10バイト受信しようとして2バイト受信したところで一旦recvが復帰するようなことは普通にあります。LAN上では一回で受信できることがほとんどでも、間にルータや高機能なブリッジが挟まると、IPパケットの分割や連続送信などの関連でこういったことが発生します。 それで普通は電文の最初に電文長を指定して、そのバイト数分受信するまで受信を繰り返します。 復帰値として-1か例外が発生しているのであればネットワークエラーと思えますが、0バイト受信でエラーとするのはどうでしょう... どうしても気になるようでしたら、0バイト受信を繰り返す上限を(例えば連続10回まで)としておき、それを超える場合には警告をログに出力して切断するようにすればよいと思います。 できればIPトレースを取って、0バイト受信が発生した時のパケットを見てみるといいと思います。

  • bgbg
  • ベストアンサー率53% (94/175)
回答No.2

FTP転送を自前で処理されているのですか?

関連するQ&A

  • Weblogic状態監視

    以下の環境でWeblogicがハングした際、メールを飛ばしたいのですが、WeblogicもしくはSolarisでの設定をおしえてください。 宜しくお願いします。 ■環境 Solaris 9 JDK1.3.1_08 Weblogic Server7.0 SP4

    • ベストアンサー
    • Java
  • Socket通信だけでSQL Serverにアクセス

    一般的なC言語のソケット通信関数のみを使用して、SQL Serverに接続する方法を探しています。 今回使用するハードウェアは、Windows PCではなく、Ethernetの付いた小型の組み込み用CPUボード(CPUはARM7)なので、ODBCなど立派なデータベースサポート環境など全くありません。 この為、C言語を使ってソケット通信にて自力でSQLサーバーに接続しなければなりません。 しかし、私はC言語でのソケット通信プログラム作成能力はあっても、SQLサーバとのやり取りにつきましては、何一つ分からない状態です。 ネットでいろいろと検索しましても、1433ポートを使用するなど極めて断片的な情報は得られた物の、具体的に何をするのかが分かりませんでした。 そこで、Socket通信関数群だけを使用してSQLサーバーにアクセスする方法についてご存じの事がございましたら、是非ともご教示頂けませんでしょうか。 情報が書かれているWEBページとか、あるいは書物とか、あるいは具体的なソースコードなどなど... 何でも構いませんので、宜しくお願い致します。 ※具体的にどの様なSQL Serverを使用するのかは、現在客先にて調整中でまだ分かりません。  各種SQLサーバーに共通的な方法が存在するのでしょうか? それとも、SQLサーバーによって全て方法が異なるのでしょうか?

  • TCP通信

    OS:Win2000、VisualBasic.netで開発しています。 現在TCP通信のプログラムを製造しています。 TCPサーバとTCPクライアントのテストアプリケーションを作成し、接続テストを行っているのですが、 サーバとクライアントの接続、データ送受信の確認はできました。 しかし、一度クライアント側から接続を切断(ソケットを消去)し、 再びソケットを生成してコネクト要求を出しても接続が確立できません。 このときサーバ側はなにも操作していません。 終始接続待機状態にしてあります。 ソースがないと分かりにくいかもしれませんが、 何か思い当たることがある方、アドバイスよろしくお願いします。

  • ディレクトリ構成、権限、グループのコピー

    サーバのディレクトリ構成、権限、グループのコピーをしたいのですが、 よい方法を伝授していただきたく。 ファイルの転送は現時点では一切必要ないです、いずれ個別に配置していきます。 ※ファイルが膨大にあるため、ファイル転送してから削除はNGです。 サーバは2台ともSolarisを利用しています。 転送は(A)Solaris9→(B)Solaris10.5です。 コマンドやパイプを駆使してできるものなのでしょうか。。。

  • UDP通信での受信方法について

    MFCでUDPプロトコルを使ったサーバー・クライアントをソケットプログラムで書いております。 ソフトの内容は、クライアントから送信されたの文字列のコマンドをサーバで処理をするだけです。 サーバー側での受信の仕方は WSAAsyncSelect()関数を使ってソケットイベントが発生するごとに親ウィンドウに自作のメッセージ(WM_MY_MSG)が送られるように設定する ↓ WM_MY_MSGのメッセージハンドラ内でrecvfrom()関数を使って受信する。 という方法を用いています。クライアント2台ぐらいであれば正常に動きます。 質問1: まだ試したことはないのですが(というより試す環境がない)、ほぼ同時ぐらいに複数(10台ぐらい)のクライアントからコマンドが送信された場合、それを全部正確に受信できるものなのでしょうか?要するに一つのコマンドを処理中に別のコマンドが送られてきた場合の動作はどうなるのでしょうか? 質問2: UDP通信での受信をする場合の何かもっとスタンダードな方法があるのでしょうか? よろしくお願いします。

  • socketでのバイナリファイルの扱い方

    javaのsocketを用いてファイルの送信サーバ、受信クライアントを作成しているのですが テストプログラムとしてスレッド化せずに送信・受信部のみ作りました。 症状はバイナリデータの転送がうまくできないことです。ソースを抜粋すると サーバ側で BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());//socketはSocketクラス BufferedInputStream in1 = new BufferedInputStream( new FileInputStream("test1.bmp")); BufferedInputStream in2 = new BufferedInputStream( new FileInputStream("test2.bmp")); while( (c = in1.read() ) != -1 ){   out.write(c); } while( (c = in2.read() ) != -1 ){   out.write(c); } クライアント側で BufferedOutputStream out1 = new BufferedOutputStream( new FileOutputStream("test1.out.bmp") ); BufferedOutputStream out2 = new BufferedOutputStream( new FileOutputStream("test2.out.bmp") ); BufferedInputStream in = new BufferedInputStream( s.getInputStream() ); while( ( c=in.read() ) != -1 ){   out1.write(c); } while( ( c=in.read() ) != -1 ){   out2.write(c); } とやっています。 クライアント側で1回目のin.readを抜けるときにはサーバ側は既に2回のwriteを終わっているようで ファイルはtest1.out.bmpにマージされていました。 サーバ側の1回目のwriteのオブジェクトがcloseしていないことが原因だと思い1回目のwriteが終わった時点でout.close()とした のですがそうやるとsocketも閉じてしまいsocket closeのエラーが生じてしまいました。 このようにならず1本のコネクションでバイナリのデータを複数送信する方法をご存知でしたら教えてください。 [環境] win2ksp1a,j2sdk1.4.1_03,java経験4ヶ月程度

  • ソケット通信で、250本しか接続できない

    solaris上で、ソケット通信をするプログラムを作成しております。 サーバー側にクライアントを多数接続したいのですが、 250本くらい接続するとサーバー側でacceptを呼び出したタイミングで セグメント例外を出力して異常終了してしまいます。 ここからは推測なのですが、 サーバー側のディスクリプタが255までは正常に動作するため、 ディスクリプタの数が256に制限されているのではないかと思います。 そこで、ulimitでdescriptorsを増やしたり、 setrlimit関数で、RLIMIT_NOFILE値を増やしたりしてみましたが、 状況は全く変わりませんでした。 念のためスタックサイズを増やしてもみましたがやはり効果ありませんでした。 どなたか、解決方法をご存じでしたら、ご教授頂けませんか? よろしくお願いします。

  • web系システムのテストについて

    web系システムにおけるテストについてですが、 一般的には単体テスト、結合テスト、システムテストなどありますが、 web系の場合、どこまでが単体でどこまでが結合でといった境界 がはっきりしません。 たとえば、サーバサイドのjavaの場合、JSP、javaScript、HTML、java など複数の要素が含まれており、なにをもって単体と呼ぶかがわか らず、strutsなどのフレームワークを利用した場合はさらに MVCと機能が分離するためさらにテストが複雑です。 テストフェーズ別の具体的な成果物や、テスト項目、 テスト内容などをご教授いただけないでしょうか。 よろしくおねがいします。

  • Java(クライアント)とC言語(サーバ)間のソケット通信 サーバ再起動時のbindエラー

    サーバ側がC言語(Linux)、クライアント側がJavaのソケット通信プログラムを書いているのですが、いきなりつまづいてしまったため質問失礼します。 ソースとしては以下の2つのソースをテストとして利用させて頂きました。 ローカルネットワーク内の2台にそれぞれを設置し、それにあわせてIPとポートは変更してあります。 http://www.aihara.co.jp/~junt/program/socket/inet_server.c http://www.hellohiro.com/src/HelloWorldSocketClient.java サーバプログラムを少し変更し(http://oshiete1.goo.ne.jp/qa5565926.html)、サーバ起動→クライアント起動でサーバクライアント間通信を行えることを確認しました。 しかし、もう一度テストしてみようと直後にサーバプログラムを起動すると、bindでエラーを吐いてしまい接続待機状態にできませんでした。 少し待ってから起動したりポートを変えて実行すると正常に待機状態にできるため、プログラム終了時のソケットのクロージングが正常に行われずポートの競合が起きていることが原因だとは思うのですが、ソケットのcloseはサーバもクライアントも書いてあるため自分には解決方法が思いつきませんでした。 ちなみに、サーバプログラムのソースと併せて公開されているC言語クライアントプログラムを用いた場合は再起動してもbindエラーが出ることはありませんでした。 この問題の原因と考えられることと解決案をアドバイス願えませんでしょうか。よろしくお願いします。 以下、開発環境です。 ■C言語 OS:Fedora 12 エディタ:一応VisualC++2008(Linux用に書いているので実質ただのテキストエディタ) コンパイラ:標準gcc ■Java OS:Windows XP SP3 エディタ・コンパイラ:eclipse ※実装先の都合上、winsockによるサーバに変えるや言語の変更はできません。

  • FTPサイト上で圧縮ファイルを解凍する方法を教えてください。

    FTPサイト上で圧縮ファイルを解凍する方法を教えてください。 Windows上の多数のファイルをSolarisサーバにFTP転送する際、 エクスプローラを使用して行っているのですが、非常に時間が かかっています。 そこで、圧縮して転送することを考えたのですが、それには 転送先サーバで解凍する必要があります。 telnetやsshといった方法でのログインは不可であり、ftpだけで 解凍を行いたいのですが、可能でしょうか。 良い方法があれば、教えていただけないでしょうか。 なお、Windows上に高速転送ソフトなどをインストールすることは できません。 よろしくお願いします。

専門家に質問してみよう