有 3 年以上工作经验的请进, *高手手请进 ! 一个巨难的 FTP 的问题 !

时间:2022-10-23 15:34:08
各位好: 
       最近本人实施的项目过程出现了一个巨难的题目,请各位帮忙.

项目名称: 网关系统 GateWay (java 开发)

系统简介, 我们原来的网关系统负责将公司下面几十家门店的资料在晚上 FTP 上传到老的网关系统,用的是 WIN2000 自带的 FTP 服务. 现在我们准备用新的 java
开发的 FTP 服务器, 不用 win 2000 Server 自带的 FTP 服务 .

1: 原来下面的门店可以用 win 2000 ftp 服务正确上下传文件

2: 我们下面的门店拨号上网后通过一个终端软件将文件上传,  
  我们的 FTP 服务器都会经过我们的网关 IP :  162.16.251.249 

3:  a:  我的新的 FTP 服务器当服务器和客户门店都在同一局域网内能正常上下传文件
   b:   当我的FTP 服务器拨号上网, 客户门店用拨号的因特网地址连接我的 FTP 服务
器时, 也可以正常上下传文件
   c:   出现问题只有在我的门店拨号上网, 门店用通过该FTP 服务器的外部 IP 来访问
        这个FTP 服务器(注: 该 FTP 服务器位于局域网内), 正常上下产文件

4: 现在新开发的 FTP 出现的问题: 
   a:  下面的门店可以连接登陆到我的 FTP server
   b:  但是在上传文件的时候出现异常, 异常信息如下 : 
       [06/03 00:40:40 (INF)] Handling new request from 162.16.251.249
[06/03 00:40:40 (INF)] New connection from 162.16.251.249
[06/03 00:40:41 (INF)] User login - 162.16.251.249 - admin
[06/03 00:41:05 (WAR)] java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:171)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:158)
at java.net.Socket.connect(Socket.java:426)
at java.net.Socket.connect(Socket.java:376)
at java.net.Socket.<init>(Socket.java:291)
at java.net.Socket.<init>(Socket.java:147)
at ranab.server.ftp.FtpDataConnection.getDataSocket(FtpDataConnection.java:150)
at ranab.server.ftp.FtpConnection.doSTOR(FtpConnection.java:1066)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at ranab.server.ftp.BaseFtpConnection.service(BaseFtpConnection.java:120)
at ranab.server.ftp.BaseFtpConnection.run(BaseFtpConnection.java:96)
at java.lang.Thread.run(Thread.java:536)

c: 注释:  162.16.251.249 是我公司的局域网的网关
d: 注释:  出错的一行FtpDataConnection.java:150
mDataSoc = new Socket(mAddress, miPort) 这里

FtpDataConnection.getDataSocket 相关代码如下
             /**
     * Get the data socket. In case of error returns null.
     */
    public Socket getDataSocket() {

        try {

            // get socket depending on the selection
            if(mbPort) {
                mDataSoc = new Socket(mAddress, miPort);
            }
            else if(mbPasv) {
                mDataSoc = mServSoc.accept();
            }
        }
        catch(Exception ex) {
            mConfig.getLogger().warn(ex);
            mDataSoc = null;
        }

e: 本人发现在我的 FTP 服务器引擎程序中一段: 
   public void run() {
        while (mRunner != null) {
            try {
                Socket datasocket = mServerSocket.accept();
                //add test
                String clientip = datasocket.getInetAddress().getHostAddress() ;
                int clientport = datasocket.getPort() ;
                System.out.println("SeverEngine.clientip = " + clientip) ;
                System.out.println("SeverEngine.clientport = " + clientport) ;
                mServer.serveRequest(datasocket);
            }
            catch (Exception ex) {
            }
        }
    }

在这里我发现这个 datasocket 得到的客户门店的 IP clientip 总是为我公司的网关地
址: 162.16.251.249 , 为什么这个客户端能够登陆我的 FTP 服务器, 一上传文件就会有
错, 是不是局域网内服务器与外面有 Socket 通信时, 这个 Socket 的客户端 IP 总是
显示为该局域网网关的 IP 地址, 如果有问题, 那为什么, 同样的情况的下, 其他的都
不变, 客户端能正常上下传 win2000 自带的 FTP 服务. 百思不得其解, 希望各位高手
不吝赐教哦  !!!

联系 QQ:  44501839
邮件:      qyghost@sina.com

14 个解决方案

#1


#2


帮着 顶

#3


ftp协议需要使用20,21两个port,服务器在传输命令时使用21,传输数据时使用20
当要进行传输时,客户端打开一个1024以上的随机端口,同时在已经和服务器建立连接的命令端口21上传输PORT命令,要求服务器使用20端口连接客户端刚打开的随机端口,服务器这才使用自己的20端口建立与客户端的连接,传送完文件后服务器将20端口关闭。

你们的程序好像并没有完整解析ftp协议,没有取得客户端打开的随机端口号,所以不能建立主动的数据传输连接。当然也可以建立被动的数据传输连接,但是还是需要完整解析ftp协议。
由于网关对ip包进行了转发,你们没有取得客户的ip地址也是有可能的,具体要看你们的网关是哪一类网关。

#4


package jdeveloper.ftp;
import sun.net.ftp.*;
import sun.net.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.*;

public class FtpApplet extends Applet
{
FtpClient aftp;
DataOutputStream outputs ;
TelnetInputStream ins;
TelnetOutputStream outs;
TextArea lsArea;
Label    LblPrompt;
Button   BtnConn;
Button   BtnClose;
TextField  TxtUID;
TextField  TxtPWD;
TextField  TxtHost;
int ch;
public String a="没有连接主机";
       String hostname="";
public void init () {
setBackground(Color.white);
setLayout(new GridBagLayout());
GridBagConstraints GBC = new GridBagConstraints();
LblPrompt = new Label("没有连接主机");
LblPrompt.setAlignment(Label.LEFT);

BtnConn = new Button("连接");
BtnClose = new Button("断开");
BtnClose.enable(false);
TxtUID = new TextField("",15);
TxtPWD = new TextField("",15);
TxtPWD.setEchoCharacter('*');
TxtHost = new TextField("",20);
Label LblUID = new Label("User ID:");
Label LblPWD = new Label("PWD:");
Label LblHost = new Label("Host:");

lsArea = new TextArea(30,80);
lsArea.setEditable(false);

GBC.gridwidth= GridBagConstraints.REMAINDER;
GBC.fill     = GridBagConstraints.HORIZONTAL;
((GridBagLayout)getLayout()).setConstraints(LblPrompt,GBC);
add(LblPrompt);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblHost,GBC);
add(LblHost);
GBC.gridwidth=GridBagConstraints.REMAINDER;
((GridBagLayout)getLayout()).setConstraints(TxtHost,GBC);
add(TxtHost);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblUID,GBC);
add(LblUID);
GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(TxtUID,GBC);
add(TxtUID);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblPWD,GBC);
add(LblPWD);
GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(TxtPWD,GBC);
add(TxtPWD);

GBC.gridwidth=1;
GBC.weightx=2;
((GridBagLayout)getLayout()).setConstraints(BtnConn,GBC);
add(BtnConn);
GBC.gridwidth=GridBagConstraints.REMAINDER;

((GridBagLayout)getLayout()).setConstraints(BtnClose,GBC);
add(BtnClose);

GBC.gridwidth=GridBagConstraints.REMAINDER;
GBC.fill     = GridBagConstraints.HORIZONTAL;
((GridBagLayout)getLayout()).setConstraints(lsArea,GBC);
add(lsArea);
       }

public boolean connect(String hostname, String uid,String pwd)
{
               this.hostname = hostname;
LblPrompt.setText("正在连接,请等待.....");
try{
 aftp =new FtpClient(hostname);
 aftp.login(uid,pwd);
 aftp.binary();
 showFileContents();
}
catch(FtpLoginException e){
a="无权限与主机:"+hostname+"连接!";
LblPrompt.setText(a);
return false;
}
catch (IOException e){
a="连接主机:"+hostname+"失败!";
LblPrompt.setText(a);
return false;
}
catch(SecurityException e)
{
a="无权限与主机:"+hostname+"连接!";
LblPrompt.setText(a);
return false;
}
LblPrompt.setText("连接主机:"+hostname+"成功!");
return true;
}

public void stop()
{
try
{
aftp.closeServer();
}
catch(IOException e)
{
}
}

public void paint(Graphics g){
}

public boolean action(Event evt,Object obj)
{
if (evt.target == BtnConn)
{
LblPrompt.setText("正在连接,请等待.....");
if (connect(TxtHost.getText(),TxtUID.getText(),TxtPWD.getText()))
{
BtnConn.setEnabled(false);
BtnClose.setEnabled(true);
}
return true;
}
if (evt.target == BtnClose)
{
stop();
BtnConn.enable(true);
BtnClose.enable(false);
LblPrompt.setText("与主机"+hostname+"连接已断开!");
return true;
}
return super.action(evt,obj);
}
public boolean sendFile(String filepathname){
boolean result=true;
if (aftp != null)
{
LblPrompt.setText("正在粘贴文件,请耐心等待....");

String  contentperline;
try{
a="粘贴成功!";
String fg =new  String("\\");
int index = filepathname.lastIndexOf(fg);
String filename = filepathname.substring(index+1);
File localFile ;
localFile = new File(filepathname) ;
RandomAccessFile sendFile = new RandomAccessFile(filepathname,"r");
//
sendFile.seek(0);
outs = aftp.put(filename);
outputs = new DataOutputStream(outs);
while (sendFile.getFilePointer() < sendFile.length() )
{
 ch = sendFile.read();
 outputs.write(ch);
}
outs.close();
sendFile.close();
}
catch(IOException e){
 a = "粘贴失败!";
 result = false ;

}
LblPrompt.setText(a);
showFileContents();
}
else{
result = false;
}
return result;
}

public void showFileContents()
{
StringBuffer buf = new StringBuffer();
lsArea.setText("");
try
{
ins= aftp.list();
while ((ch=ins.read())>=0){
 buf.append((char)ch);
}
   lsArea.appendText(buf.toString());
ins.close();
       }
catch(IOException e)
{
}
}
       public static void main(String args[]){
            Frame f = new Frame("FTP Client");
            f.addWindowListener(new WindowAdapter(){
              public void windowClosing(WindowEvent e){
                  System.exit(0);
              }

            });
            FtpApplet ftp = new  FtpApplet();
            ftp.init();
            ftp.start();
            f.add(ftp);
            f.pack();
            f.setVisible(true);
       }
}

#5


学习

#6


UP

#7


学习!

#8


这个网关服务器中的借用了一下 rana_b ftp Server:  

资料请见:

http://www.jars.com/classes/jresout.cgi?resource=7344

相关信息:

rana_b@yahoo.com

Submitted by : Rana Bhattacharyya, rana_b@yahoo.com 
Resource URL : http://www.mycgiserver.com/~ranab 
Source Code : http://www.mycgiserver.com/~ranab 
Detailed Review : Not Available 
Type : Other 
Category : Programming - Other 
Language : Java 
Marketing : Freeware - Beta 
History : New Submission 
Version : 1.0 
Date Submitted : Mon Jul 17 18:30:49 2000

#9


学习

#10


来了

#11


up

#12


喔来了

#13


来了

#14


学习学习!深奥!

#1


#2


帮着 顶

#3


ftp协议需要使用20,21两个port,服务器在传输命令时使用21,传输数据时使用20
当要进行传输时,客户端打开一个1024以上的随机端口,同时在已经和服务器建立连接的命令端口21上传输PORT命令,要求服务器使用20端口连接客户端刚打开的随机端口,服务器这才使用自己的20端口建立与客户端的连接,传送完文件后服务器将20端口关闭。

你们的程序好像并没有完整解析ftp协议,没有取得客户端打开的随机端口号,所以不能建立主动的数据传输连接。当然也可以建立被动的数据传输连接,但是还是需要完整解析ftp协议。
由于网关对ip包进行了转发,你们没有取得客户的ip地址也是有可能的,具体要看你们的网关是哪一类网关。

#4


package jdeveloper.ftp;
import sun.net.ftp.*;
import sun.net.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.*;

public class FtpApplet extends Applet
{
FtpClient aftp;
DataOutputStream outputs ;
TelnetInputStream ins;
TelnetOutputStream outs;
TextArea lsArea;
Label    LblPrompt;
Button   BtnConn;
Button   BtnClose;
TextField  TxtUID;
TextField  TxtPWD;
TextField  TxtHost;
int ch;
public String a="没有连接主机";
       String hostname="";
public void init () {
setBackground(Color.white);
setLayout(new GridBagLayout());
GridBagConstraints GBC = new GridBagConstraints();
LblPrompt = new Label("没有连接主机");
LblPrompt.setAlignment(Label.LEFT);

BtnConn = new Button("连接");
BtnClose = new Button("断开");
BtnClose.enable(false);
TxtUID = new TextField("",15);
TxtPWD = new TextField("",15);
TxtPWD.setEchoCharacter('*');
TxtHost = new TextField("",20);
Label LblUID = new Label("User ID:");
Label LblPWD = new Label("PWD:");
Label LblHost = new Label("Host:");

lsArea = new TextArea(30,80);
lsArea.setEditable(false);

GBC.gridwidth= GridBagConstraints.REMAINDER;
GBC.fill     = GridBagConstraints.HORIZONTAL;
((GridBagLayout)getLayout()).setConstraints(LblPrompt,GBC);
add(LblPrompt);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblHost,GBC);
add(LblHost);
GBC.gridwidth=GridBagConstraints.REMAINDER;
((GridBagLayout)getLayout()).setConstraints(TxtHost,GBC);
add(TxtHost);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblUID,GBC);
add(LblUID);
GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(TxtUID,GBC);
add(TxtUID);

GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(LblPWD,GBC);
add(LblPWD);
GBC.gridwidth=1;
((GridBagLayout)getLayout()).setConstraints(TxtPWD,GBC);
add(TxtPWD);

GBC.gridwidth=1;
GBC.weightx=2;
((GridBagLayout)getLayout()).setConstraints(BtnConn,GBC);
add(BtnConn);
GBC.gridwidth=GridBagConstraints.REMAINDER;

((GridBagLayout)getLayout()).setConstraints(BtnClose,GBC);
add(BtnClose);

GBC.gridwidth=GridBagConstraints.REMAINDER;
GBC.fill     = GridBagConstraints.HORIZONTAL;
((GridBagLayout)getLayout()).setConstraints(lsArea,GBC);
add(lsArea);
       }

public boolean connect(String hostname, String uid,String pwd)
{
               this.hostname = hostname;
LblPrompt.setText("正在连接,请等待.....");
try{
 aftp =new FtpClient(hostname);
 aftp.login(uid,pwd);
 aftp.binary();
 showFileContents();
}
catch(FtpLoginException e){
a="无权限与主机:"+hostname+"连接!";
LblPrompt.setText(a);
return false;
}
catch (IOException e){
a="连接主机:"+hostname+"失败!";
LblPrompt.setText(a);
return false;
}
catch(SecurityException e)
{
a="无权限与主机:"+hostname+"连接!";
LblPrompt.setText(a);
return false;
}
LblPrompt.setText("连接主机:"+hostname+"成功!");
return true;
}

public void stop()
{
try
{
aftp.closeServer();
}
catch(IOException e)
{
}
}

public void paint(Graphics g){
}

public boolean action(Event evt,Object obj)
{
if (evt.target == BtnConn)
{
LblPrompt.setText("正在连接,请等待.....");
if (connect(TxtHost.getText(),TxtUID.getText(),TxtPWD.getText()))
{
BtnConn.setEnabled(false);
BtnClose.setEnabled(true);
}
return true;
}
if (evt.target == BtnClose)
{
stop();
BtnConn.enable(true);
BtnClose.enable(false);
LblPrompt.setText("与主机"+hostname+"连接已断开!");
return true;
}
return super.action(evt,obj);
}
public boolean sendFile(String filepathname){
boolean result=true;
if (aftp != null)
{
LblPrompt.setText("正在粘贴文件,请耐心等待....");

String  contentperline;
try{
a="粘贴成功!";
String fg =new  String("\\");
int index = filepathname.lastIndexOf(fg);
String filename = filepathname.substring(index+1);
File localFile ;
localFile = new File(filepathname) ;
RandomAccessFile sendFile = new RandomAccessFile(filepathname,"r");
//
sendFile.seek(0);
outs = aftp.put(filename);
outputs = new DataOutputStream(outs);
while (sendFile.getFilePointer() < sendFile.length() )
{
 ch = sendFile.read();
 outputs.write(ch);
}
outs.close();
sendFile.close();
}
catch(IOException e){
 a = "粘贴失败!";
 result = false ;

}
LblPrompt.setText(a);
showFileContents();
}
else{
result = false;
}
return result;
}

public void showFileContents()
{
StringBuffer buf = new StringBuffer();
lsArea.setText("");
try
{
ins= aftp.list();
while ((ch=ins.read())>=0){
 buf.append((char)ch);
}
   lsArea.appendText(buf.toString());
ins.close();
       }
catch(IOException e)
{
}
}
       public static void main(String args[]){
            Frame f = new Frame("FTP Client");
            f.addWindowListener(new WindowAdapter(){
              public void windowClosing(WindowEvent e){
                  System.exit(0);
              }

            });
            FtpApplet ftp = new  FtpApplet();
            ftp.init();
            ftp.start();
            f.add(ftp);
            f.pack();
            f.setVisible(true);
       }
}

#5


学习

#6


UP

#7


学习!

#8


这个网关服务器中的借用了一下 rana_b ftp Server:  

资料请见:

http://www.jars.com/classes/jresout.cgi?resource=7344

相关信息:

rana_b@yahoo.com

Submitted by : Rana Bhattacharyya, rana_b@yahoo.com 
Resource URL : http://www.mycgiserver.com/~ranab 
Source Code : http://www.mycgiserver.com/~ranab 
Detailed Review : Not Available 
Type : Other 
Category : Programming - Other 
Language : Java 
Marketing : Freeware - Beta 
History : New Submission 
Version : 1.0 
Date Submitted : Mon Jul 17 18:30:49 2000

#9


学习

#10


来了

#11


up

#12


喔来了

#13


来了

#14


学习学习!深奥!