質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

RHELまたはJavaのバージョン違いによるFTPの接続について

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,601

dohq

score 232

プログラミングに関係ある所か微妙に怪しいところですが、
お付き合い頂けますと幸いです。

 背景

現在、
Red Hat Enterprise Linux AS release 4 (Nahant Update 3)
から
Red Hat Enterprise Linux Server release 6.4 (Santiago)
へのシステムマイグレーション作業を行なっています。

その中に、Javaを使用したFTPファイル転送のモジュールがあるのですが、
これが旧環境だと問題無く動くのですが新環境だとエラーで失敗します。

変化があったのはREHLのバージョンと、Javaのバージョンです。
Javaのバージョンは1.4→1.8へと変化しました。

逆に言うと、変化があったのは上記2点だけのはずなのですが、
なぜ、ここで失敗しているのか分かりません。

Javaのモジュールは、FTPのコマンドそれぞれクラスで作成し、
それを実際動作を行うメインモジュールから呼び出しています。

といってもメインモジュールも複雑な事はしておらず、
ログイン→ディレクトリ移動→ファイルの存在確認→ファイルPUT
となっています。

 環境

    旧環境 新環境
OS Red Hat Enterprise Linux AS release 4 (Nahant Update 3) Red Hat Enterprise Linux Server release 6.4 (Santiago)
Java 1.4 1.8
接続先 Windows2003 Windows2003

 問題

上記の流れの中の内、
ファイル存在確認(NLST発行)

ファイル送信(PUT発行)
の2箇所が上手く動いていないようです。

ファイルが存在する場合でもファイルの存在はないと認識され、
PUTに至っては、データが流しこまれていないようなのです。
(送信先に空ファイルは存在するので、データ送信のみ上手くいってない?)

背景に書いたような環境の変化によって、上記動作が上手くいかなくなるような事はあるのでしょうか…

当方Javaについてからっきしな為、どこが問題なのかも分かりません。
お手数ですが、御知恵を拝借できましたら幸いです。
以下に使用している、FTPコマンドのクラスを添付します。

何卒宜しくお願い致します。

 ソース

import java.io.*;
import java.net.*;
import java.util.*;

/**
 * FTP Clientクラス<BR>
 *<BR>
 * RFC959仕様のFTPコマンドを発行する<BR>
 *<BR>
 */
public class FtpClient
{

    private Socket sock = null;
    private PrintWriter log = new PrintWriter(System.out);
    private boolean logflag;


   /**
    * FTPサーバにログインを行う。<BR><BR>
    * @param String server    サーバホスト名(IPアドレス等)
    * @param int Port        ポート番号(大抵は21です)
    * @param String user        ユーザー名
    * @param String pass        パスワード
    * @throws Exception         エラーが発生した場合にスローされる。
    */
    public FtpClient(String server, int Port, String user, String pass) throws Exception
    {
        logflag = true;
        this.login( server, Port, user, pass );
        logflag = false;
    }


   /**
    * FTPサーバからリプライコードを取得。<BR>
    * <BR>
    * <BR>
    * @param String        strPass エンコードしたいパスワード
    * @return int        リプライコード
    * @throws java.io.IOException 入出力エラーが発生した場合にスローされる。
    */
    private int getReplyCode() throws IOException
    {
        //↓ソケット通信の時、getInputStreamは上等手段っぽい
        // そのオブジェクトをBufferedReaderでやるかObjectInputStreamでやるかは作り手次第
        BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        String buffer;

//        buffer = reader.readLine();
//        this.log(buffer);
//        return Integer.parseInt(buffer.substring(0,3));

        do
        {
            buffer=reader.readLine();
            this.log(buffer);
        } while(buffer.charAt(3) == '-');
        return Integer.parseInt(buffer.substring(0,3));
    }

   /**
    * FTPサーバにコマンドを送信する。<BR>
    * <BR>
    * @param String        command FTPコマンド
    * @throws java.io.IOException 入出力エラーが発生した場合にスローされる。
    */
    private void sendCommand(String command) throws IOException
    {
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
        writer.write(command);
        writer.newLine();            //行区切文字を送る。\nとは限らないのでこれを使う。
        writer.flush();
        this.log(">"+command);
    }

   /**
    * FTPサーバにログイン認証を行う。<BR>
    * 通常、インスタンス生成時に呼ばれる。<BR>
    * <BR>
    * @param String server    サーバホスト名(IPアドレス等)
    * @param int Port        ポート番号(大抵は21です)
    * @param String user        ユーザー名
    * @param String pass        パスワード
    * @throws Exception         エラーが発生した場合にスローされる。
    */
    public void login(String server, int port, String user, String pass) throws Exception
    {
        sock = new Socket(server, port);
        sock.setSoTimeout(100000);


        // 接続チェック
        if(getReplyCode() != 220)
        {
            throw( new Exception("接続失敗") );
        }

        sendCommand("USER " + user);
        if(getReplyCode() != 230)
        {
            //パスワードも必要
            sendCommand("PASS " + pass);
            if(getReplyCode() != 230)
            {
                throw( new Exception("IDまたはパスワードが違います"));
            }
        }
    }

   /**
    * サーバソケットを作成する。<BR>
    * <BR>
    * @throws Exception     エラーが発生した場合にスローされる。
    */
    private ServerSocket port() throws Exception
    {
        String command = "PORT";

        //サーバソケットを作成し、指定されたバックログで指定された
        //ローカルポート番号にバインドします。
        //ポート番号に 0 を指定すると、空いているポート上にソケットが作成されます。
        //受信する接続 (接続要求) の待ち行列の最大長は、
        //backlog パラメータの値に設定されます。
        ServerSocket mySocket = new ServerSocket(0,1);

        //ポートは4桁の数字が入る?(1254とか1255とか…)
        int iPort = mySocket.getLocalPort();

        // 自マシンのIPアドレス取得
        String ip = sock.getLocalAddress().getHostAddress();

        //ここら辺は他人のソースのパクリ
        command = command + " " + ip.replace('.',',');
        command = command + "," + (iPort >> 8) + "," + (iPort & 0xFF);

        sendCommand( command );
        if( getReplyCode() != 200)
        {
            throw( new Exception(command + "は失敗しました") );
        }
        return mySocket;
    }

   /**
    * NLSTにコマンドを付記して発行する。<BR>
    * <BR>
    * @param String command    コマンド
    * @return String[]        取得したファイル情報
    * @throws Exception     エラーが発生した場合にスローされる。
    */
    public String[] nlst(String command) throws Exception
    {
        if (command.length() == 0) return listSub("NLST");
        return listSub("NLST " + command);
    }


   /**
    * LISTまたはNLSTコマンドを実行してサーバから情報取得し<BR>
    * 文字配列型で返す。<BR>
    * <BR>
    * @param String command    コマンド
    * @return String[]        取得したファイル情報
    * @throws Exception     エラーが発生した場合にスローされる。
    */
    private String[] listSub(String command) throws Exception
    {
        String resp[] = null;
        Vector v = new Vector();        //JDK1.5対策

        BufferedReader readData=null;
        ServerSocket myDataSocket = port();

        // 2002.12.06追加
        myDataSocket.setSoTimeout(5000);

        sendCommand(command);

        if(getReplyCode() != 150)
        {
            throw( new Exception(command+"は失敗しました") );
        }


        Socket socRead = myDataSocket.accept();

//        ↓e*Gateから呼び出すとウィンドウ変えたりしてると止まるときがあった。
//        acceptしたら即切り離すようにした 2002.12.09
//        同winマシン内にあるIISのFTPに対してだと、ここで処理が止まることがある・・・
        if (myDataSocket != null) myDataSocket.close();
        readData = new BufferedReader(new InputStreamReader(socRead.getInputStream()));

        String buffer = null;
        while(true)
        {
            buffer = new String();
            buffer = readData.readLine();
            if(buffer == null)
            {
                break;
            }
            v.addElement(new String(buffer));
        }

        try
        {
            if (socRead != null) socRead.close();

//            ↓acceptしたら即切り離すようにした 2002.12.09
//            if (myDataSocket != null) myDataSocket.close();

        }
        catch( IOException e ){}

        if(getReplyCode() != 226)
        {
            throw( new Exception(command+"は失敗しました") );
        }

        resp = new String[v.size()];
        for (int i = 0; i < resp.length; i++)
        {
            resp[i] = (String)v.elementAt(i);
        }
        return resp;
    }

   /**
    * ローカルファイルをサーバにファイル名つけてプットする。
    * <BR>
    * @param String localfile    ローカルファイル名
    * @param String serverfile    サーバファイル名
    * @throws Exception         エラーが発生した場合にスローされる。
    */
    public void put(String localfile, String serverfile) throws Exception
    {
        String command = "STOR";
        DataInputStream readData = null;
        DataOutputStream writeData = null;
        ServerSocket myDataSocket = null;
        Socket socWrite = null;

        try
        {
            myDataSocket = port();

            sendCommand(command + " " + serverfile);
            if(getReplyCode() != 150)
            {
                throw( new Exception(command+"は失敗しました") );
            }

            socWrite = myDataSocket.accept();
            readData = new DataInputStream(new FileInputStream(localfile));
            writeData = new DataOutputStream(socWrite.getOutputStream());

            while(true)
            {
                byte[] byteRead=new byte[10240];
                int iReadLen=readData.read(byteRead);
                if(iReadLen==(1))
                {
                    break;
                }
                writeData.write(byteRead,0,iReadLen);
            }

            writeData.close();
            readData.close();
            socWrite.close();
            if( getReplyCode() != 226)
            {
                throw( new Exception(command+"による転送は失敗しました") );
            }
        }
        catch( Exception e )
        {
            e.printStackTrace( this.log );
            throw( new Exception() );
        }
        finally
        {
            try
            {
                if (socWrite != null) socWrite.close();
                if (myDataSocket != null) myDataSocket.close();
                if (writeData != null) writeData.close();
            }
            catch( IOException e ){}
        }
    }

   /**
    * PWDを発行する。<BR>
    * <BR>
    * @return boolean            true・・・成功、false・・・失敗
    * @throws Exception         エラーが発生した場合にスローされる。
    */
    public boolean pwd() throws Exception
    {
        sendCommand("PWD");
        if(getReplyCode() != 257)
        {
            return false;
        }
        return true;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tkmtmkt

    2016/08/19 22:04

    「~の2箇所が上手く動いていない」というのを、エラーメッセージが表示されたことで判断されたのであれば、エラーメッセージも上げておいたほうが良いです。
    スタックトレース出力しているようなので、原因究明の材料になるかと思います。

    キャンセル

回答 4

+1

とりあえず、手動で ftp を実行してみて、
原因を切り分けるあたりから始めてみては
いかがでしょうか。
なんか環境設定とか違ってるかもしれませんし。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

firewallの設定は問題ないですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

RHELからの接続先はWindows2003なんですね。
・Javaをよく見たらポートを入力する場所があるので・・・

・ポート20,21のうち、20が閉じていませんか?
(Telnet ip ポート番号)で確認できます。

・ポートが固定の場合はJava側でPASVモードになっていますか?

・そもそもポート20,21ですか?

・受け側windows2003とのポート番号に差異がありませんか?

・コマンドラインでの接続はどうですか?(takasima20さんと同じ)
(コマンドラインでは成功:Javaの中での問題)←id/pass/portとか?
(コマンドラインからも失敗:linux側でのfirewallの問題(moonphaseさんと同じ)

・エラーが何かわからない(tkmtmkt)
→それぞれのエラー表示でコマンドが表示されているようですので、見たいですね。

なんとなくネットワーク(ポート関係)かなぁと思いますーーー

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

0

解答下さったみなさん、ありがとうございました。
頂いた内容を確認していきましたところ、
結局はこちらのコーディングミスでした。
接続先のOSがWindowsServer2012の為、IISからのレスポンスコードに一部
変更が入っていたようでした。
そこの対応が出来ていなかったようです。

自己解決となってしまいましたが、みなさんありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る