基本 Java 文件服务器
我正在尝试创建一个非常准系统的文件服务器,它除了下载 zip 文件并退出之外什么也不做,但我遇到了问题。我有两个主要问题。
第一个是,当我在本地主机上测试时,它可以工作,因为它传输 zip 文件,但是当我尝试打开它时,我收到一个关于它已损坏的错误。这可能与 zip 文件格式或我传输它的方式有关。
第二个问题是,每当我使用除 localhost 之外的任何内容时,它都会失败。我尝试过将网站重定向到我的 IP,然后输入我的 IP 地址,但都失败了,即使我关闭了所有防火墙和防病毒软件。
服务器代码:
import java.io.*;
import java.net.*;
public class FileServer {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44444;
ServerSocket serverSock = null;
PrintWriter out = null;
BufferedInputStream bin = null;
OutputStream os = null;
Socket clientSock = null;
File file;
byte[] fileData;
String filename = "file.zip";
while(true) {
try {
//Listen on port
serverSock = new ServerSocket(PORT_NUMBER);
//Get connection
clientSock = serverSock.accept();
System.out.println("Connected client");
//Get output stream
out = new PrintWriter(clientSock.getOutputStream(), true);
out.println(filename); //Print filename
file = new File(filename); //Get file
fileData = new byte[(int)file.length()]; //Stores the file data
bin = new BufferedInputStream(new FileInputStream(file));
out.println((int)file.length()); //Print filesize
bin.read(fileData); //Read contents of file
os = clientSock.getOutputStream();
os.write(fileData); //Write the file data
os.flush();
} catch(SocketException e) {
System.out.println("Client disconnected");
} catch(Exception e) {
System.out.println(e.getMessage());
System.exit(1);
} finally {
//Close all connections
System.out.println("Shutting down");
if(os != null) {
os.close();
}
if(bin != null) {
bin.close();
}
if(out != null) {
out.close();
}
if(clientSock != null) {
clientSock.close();
}
if(serverSock != null) {
serverSock.close();
}
}
}
}
}
客户端代码片段,假设所有语法都是正确的,并且其他所有内容都存在并且正常工作,因为当我剪切片段时,我可能不匹配一些大括号或其他内容。
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public static void main(String[] args) {
final int PORT_NUMBER = 44444;
final String HOSTNAME = "127.0.0.1";
String filename = "default.txt";
Socket sock = null;
BufferedReader in = null;
BufferedOutputStream bos = null;
InputStream is = null;
byte[] fileData;
//Attempt to connect
try {
sock = new Socket(HOSTNAME, PORT_NUMBER);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
is = sock.getInputStream();
} catch(UnknownHostException e) {
JOptionPane.showMessageDialog(this, "Error: could not connect to host " + HOSTNAME + " on port number " + PORT_NUMBER);
System.exit(1);
} catch(ConnectException e) {
JOptionPane.showMessageDialog(this, "Error: connection refused");
System.exit(1);
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
try {
filename = in.readLine();
bos = new BufferedOutputStream(new FileOutputStream(filename));
fileData = new byte[Integer.decode(in.readLine())]; //Gets file size
is.read(fileData);
bos.write(fileData);
bos.flush();
bos.close();
if(is != null) {
is.close();
}
if(in != null) {
in.close();
}
if(bos != null) {
bos.close();
}
if(sock != null) {
sock.close();
}
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
JOptionPane.showMessageDialog(this, "Download complete");
}
}
}
编辑
:它在具有 .doc 和 .docx 文件的本地主机上运行得很好,只有 .zip 会导致问题。
I am trying to create a very barebones fileserver that does nothing more than download a zip file and exit, but I am running into problems. I have two main problems.
The first is that when I test on localhost, it sort of works, in that it transfers the zip file, but when I try to open it, I get an error about it being corrupt. It may be something to do with the zip file format, or how I am transferring it.
The second problem is that it fails whenever I use anything but localhost. I have tried a website redirect to my IP, and just putting in my ip address, and both fail, even when I turn off all firewalls and antivirus.
Server code:
import java.io.*;
import java.net.*;
public class FileServer {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44444;
ServerSocket serverSock = null;
PrintWriter out = null;
BufferedInputStream bin = null;
OutputStream os = null;
Socket clientSock = null;
File file;
byte[] fileData;
String filename = "file.zip";
while(true) {
try {
//Listen on port
serverSock = new ServerSocket(PORT_NUMBER);
//Get connection
clientSock = serverSock.accept();
System.out.println("Connected client");
//Get output stream
out = new PrintWriter(clientSock.getOutputStream(), true);
out.println(filename); //Print filename
file = new File(filename); //Get file
fileData = new byte[(int)file.length()]; //Stores the file data
bin = new BufferedInputStream(new FileInputStream(file));
out.println((int)file.length()); //Print filesize
bin.read(fileData); //Read contents of file
os = clientSock.getOutputStream();
os.write(fileData); //Write the file data
os.flush();
} catch(SocketException e) {
System.out.println("Client disconnected");
} catch(Exception e) {
System.out.println(e.getMessage());
System.exit(1);
} finally {
//Close all connections
System.out.println("Shutting down");
if(os != null) {
os.close();
}
if(bin != null) {
bin.close();
}
if(out != null) {
out.close();
}
if(clientSock != null) {
clientSock.close();
}
if(serverSock != null) {
serverSock.close();
}
}
}
}
}
Client code snippet, assume that all syntax is correct and everything else exists and works, because I probably mismatched some braces or something when I cut the snippet out.
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public static void main(String[] args) {
final int PORT_NUMBER = 44444;
final String HOSTNAME = "127.0.0.1";
String filename = "default.txt";
Socket sock = null;
BufferedReader in = null;
BufferedOutputStream bos = null;
InputStream is = null;
byte[] fileData;
//Attempt to connect
try {
sock = new Socket(HOSTNAME, PORT_NUMBER);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
is = sock.getInputStream();
} catch(UnknownHostException e) {
JOptionPane.showMessageDialog(this, "Error: could not connect to host " + HOSTNAME + " on port number " + PORT_NUMBER);
System.exit(1);
} catch(ConnectException e) {
JOptionPane.showMessageDialog(this, "Error: connection refused");
System.exit(1);
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
try {
filename = in.readLine();
bos = new BufferedOutputStream(new FileOutputStream(filename));
fileData = new byte[Integer.decode(in.readLine())]; //Gets file size
is.read(fileData);
bos.write(fileData);
bos.flush();
bos.close();
if(is != null) {
is.close();
}
if(in != null) {
in.close();
}
if(bos != null) {
bos.close();
}
if(sock != null) {
sock.close();
}
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
JOptionPane.showMessageDialog(this, "Download complete");
}
}
}
}
EDIT: It works just fine on localhost with .doc and .docx files, it is only .zip that causes problems.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我在您的客户端上看到两个问题,这可能会导致问题:
您正在使用 BufferedReader 读取第一行,然后使用 is.read(fileData 从套接字访问普通的底层 InputStream );
首先,BufferedReader(及其 InputStreamReader)可能读取的不仅仅是 readLine() 上的第一行 - 其余部分会被缓冲以供以后检索,但您不会读取任何内容更多的。因此您可能会丢失文件的开头。
其次,您的套接字输入流只有一个主要的
read
,它可能会也可能不会填充整个数组,因为您不检查此方法调用的结果。因此,文件的末尾可能由零字节组成,而不是实际数据(当然,会有与第一个问题中错过的一样多的零字节)。您应该在循环中读取(然后可能立即写入文件),检查(并添加)读取调用的结果。编辑:
仅用于读取数组:
我认为,
DataInputStream
中有一个readFully()
方法,它就是执行此操作的。如果你有更大的文件,你不会希望它完全在一个数组中,而是交替读写(使用较小的数组作为缓冲区):
我只能推测为什么它与 doc 一起工作 - 你真的比较了输出文件吗?也许您的 Word 文档比您的 zip 文件小,因此第二个问题并不真正适用,因为所有文件都可以一步读取。
同样的(第二个)问题实际上也适用于您读取文件的服务器。
您可能会考虑使用 DataInputStream(以及服务器端的 DataOutputStream) - 它也允许读取字符串,而不需要 Writer(和额外的缓冲)。
I see two problems on your client, which may cause problems:
You are using a
BufferedReader
to read the first line, and then access the plain underlying InputStream from the socket withis.read(fileData);
First, the BufferedReader (and it's InputStreamReader) may read more than only the first line on
readLine()
- the rest is buffered for later retrieval, but you don't read anything more. So you may be missing the start of your file.Second, you have only one main
read
for your socket-InputStream, which may or may not fill the whole array, since you don't check the result of this method call. Thus the end of the file may be consisting of zero-bytes instead of the real data (and certainly there will be as much zero bytes as you missed for the first problem). You should instead read (and then maybe instantly write to the file) in a loop, checking (and adding) the results of the read call.Edit:
For reading only into the array:
There is a
readFully()
method inDataInputStream
which does just this, I think.If you have bigger files, you would not want it completely in one array, but read and write alternately (using a smaller array as a buffer):
I can only speculate why it works with doc - did you really compare the output files? Maybe your Word documents are smaller then your zip file, and thus the second problem did not really apply, since all the file could be read in one step.
The same (second) problem actually applies to your server for reading the file, too.
You may think about using a
DataInputStream
(and DataOutputStream at the server side) - it allows reading Strings too, without needing a Writer (and additional Buffering).你在你的内部IP上尝试过吗?它应该也能工作,问题只是 NAT 或来自互联网的类似内容。
对于您的文件,md5sum 是否相同?
Did you try it on your internal IP? It should also work, and the problem would only be NAT or stuff like that from the internet.
For your file, are the md5sums identical?
您应该将您正在侦听的 IP 设置为您的 LAN IP。您正在使用
127.0.0.1
;它只接受来自本地主机的请求。You should set the IP you're listening to your LAN IP. You're using
127.0.0.1
; which accepts requests from localhost only.