我收到“INFO:远程计算机已断开连接:协议错误:数据包太长:65580”错误,当我尝试执行时:
sUpload("server.host.com", "username", "/home/localuser/.ssh/id_rsa", "filename", "");
文件未传输到SFTP服务器(另一端只创建零字节)。当通过Unix shell手动SFTP时,一切正常。我在网上看到它可能是SftpClient中BLOCK_SIZE的问题,但首先我找不到改变大小的setter方法,其次,看来默认值是65535,这完全不能解释错误的65580值消息。
有什么想法吗?
我有以下使用Java Ssh Tools的实用程序方法(j2ssh-core-0.2.9.jar):
private static void sUpload(String ftpServer, String user, String password,
String localFile, String remoteFile) throws IOException {
String methodName = "sUpload: ";
System.out.println(" START ftpServer="+ftpServer+" user="+user+" password="+password);
int result = 0;
System.out.println("ftpServer " + ftpServer);
System.out.println("user " + user);
System.out.println("password " + password);
System.out.println("localFile " + localFile);
System.out.println("remoteFile " + remoteFile);
SshClient ssh = new SshClient();
ssh.connect(ftpServer);
System.out.println("Server Connected ");
if (password.contains("\\") || password.contains("/")) {
PublicKeyAuthenticationClient pk =
new PublicKeyAuthenticationClient();
pk.setUsername(user);
// Open up the private key file
SshPrivateKeyFile file = SshPrivateKeyFile
.parse(new File(password));
SshPrivateKey key = file.toPrivateKey(null);
pk.setKeyfile(password);
pk.setKey(key);
// Try the authentication
result = ssh.authenticate(pk);
} else {
// Create a password authentication instance
PasswordAuthenticationClient pwd =
new PasswordAuthenticationClient();
// Get the users name
pwd.setUsername(user);
// Get the password
pwd.setPassword(password);
// Try the authentication
result = ssh.authenticate(pwd);
}
System.out.println("Result fromssh.authenticate(pwd) " + result);
// Evaluate the result
if (result == AuthenticationProtocolState.COMPLETE) {
// The connection is authenticated we can now do some real work!
SftpClient sftp = ssh.openSftpClient();
System.out.println("openSftpClient");
// Upload a file
if(remoteFile != null && remoteFile.trim().length() > 0){
sftp.put(localFile, remoteFile);
System.out.println("======== no remote ======================================== file transfer success =======================================================================");
}
else {
System.out.println("================================================ file transfer starting =======================================================================");
sftp.put(localFile);
System.out.println("================================================ file transfer success =======================================================================");
}
// Quit
sftp.quit();
ssh.disconnect();
}
System.out.println(" END ");
}
答案 0 :(得分:1)
ssh客户端应该告诉服务器所需的最大数据包大小是什么,服务器应该符合规范。
尝试使用其他服务器并检查自己服务器的最大数据包大小配置。
答案 1 :(得分:1)
看起来以下代码有效 - 我使用较低级别的“com.sshtools.j2ssh.sftp.SftpSubsystemClient”而不是“com.sshtools.j2ssh.SftpClient”并使用输入/输出流读取/写入文件:
System.out.println("Result fromssh.authenticate(pwd) " + result);
// Evaluate the result
if (result == AuthenticationProtocolState.COMPLETE) {
SftpSubsystemClient sftpSubsystemClient = ssh.openSftpChannel();
com.sshtools.j2ssh.connection.Channel sftpChannel = sftpSubsystemClient;
System.out.println("Local packet size: " + sftpChannel.getLocalPacketSize());
System.out.println("Remote packet size: " + sftpChannel.getRemotePacketSize());
SftpFile file = sftpSubsystemClient.openFile(remoteFile, SftpSubsystemClient.OPEN_CREATE | SftpSubsystemClient.OPEN_WRITE);
FileAttributes attrs = file.getAttributes();
attrs.setPermissions("rwxrwxrwx");
sftpSubsystemClient.setAttributes(file, attrs);
final int bufferSize = 4096;
System.out.println("Creating buffered streams");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(localFile), bufferSize);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new SftpFileOutputStream(file)));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
System.out.println("Done writing streams");
out.close();
in.close();
sftpSubsystemClient.close();
ssh.disconnect();
}
System.out.println(" END ");
真正有趣的是我输出远程和本地数据包大小只是为了好玩,它们都等于65535.看起来这个65580消息似乎是SSH服务器或SSH工具中的一个错误。
答案 2 :(得分:0)
您无法更改BLOCKSIZE。有几个地方提到了块大小。所有这些都是为某些读或写缓冲区使用固定值,或者在Cipher对象上调用getBlockSize()
,Cipher对象是JVM加密子系统的一部分。
我无法重现您所看到的错误。 SI尝试使用几种不同大小的文件,包括您提到的确切大小。像这样的东西很容易受到客户端和服务器设置的影响。
我的直觉是,j2ssh库中存在一个与密码块大小相关的错误,它通过不考虑某处的数据包标头来创建大于允许的块。我建议摆弄设置,看看你是否可以强制客户端使用不同的密码。下载j2ssh源并尝试直接调试问题也可能有所帮助。确定错误是在第一个,最后一个还是某个中间数据包上发生。