我正在从Android平板电脑客户端向Windows 7上运行的Java应用程序发送一个pdf文件。该文件总是以零字节的大小到达。这有什么问题?
在将pdf文件从客户端发送到服务器之前,将文件的大小作为长值从客户端发送到服务器,此大小正确并始终到达服务器。对于pdf文件,我正在使用此测试,大小为566718字节。
如何让pdf文件以正确的尺寸到达?
服务器代码
public class Server {
ServerSocket serverSocket;
Socket socket;
boolean runner = true;
Server() throws IOException{
serverRunner();
System.out.println("server constructor started");
} // Server() constructor
public void serverRunner() throws IOException {
System.out.println("serverrunner started");
try {
serverSocket = new ServerSocket(6789, 100);
runner = true;
while (runner) {
socket = serverSocket.accept();
MultiThreader multi = new MultiThreader(socket);
Thread t = new Thread(multi);
t.start();
} // while runner
} catch (IOException ex) {
}
} // serverRunner()
} // class Server
public class MultiThreader implements Runnable {
Socket socket;
public int fileSizeFromClient;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public MultiThreader(Socket socket){
System.out.println("print out from multithreader class");
this.socket = socket;
} // multiThreader
@Override
public void run() {
System.out.println("multi threader started");
// action #1 read file from client =====================================
// transfer.pdf read this file sent from android device to this computer
int bufferSize = 0;
try {
bis = new BufferedInputStream(socket.getInputStream());
dis = new DataInputStream(bis);
fileSizeFromClient = dis.readInt();
System.out.println("file size from client is " + fileSizeFromClient);
File fileDirectory = new File("C:/DOWNLOAD/");
if (!fileDirectory.exists()) {
fileDirectory.mkdir();
}
File file = new File("C:/DOWNLOAD/transfer.pdf");
file.createNewFile();
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
dos = new DataOutputStream(bos);
byte[] buffer = new byte[fileSizeFromClient];
int totalBytesRead = 0;
while(totalBytesRead < fileSizeFromClient){
int bytesRemaining = fileSizeFromClient = totalBytesRead;
int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
if(bytesRead == -1) {
break;
} else {
dos.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
} // while
} catch (IOException ex) {
Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
// socket.close();
} catch (IOException ex) {
Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
}
}
} // run
} // MultiThreader
客户端代码
public class MainActivity extends Activity implements Runnable {
TextView textViewOne;
Button buttonOne;
Socket socket;
private String serverIP = "192.XXX.X.X";
FileInputStream fis;
FileOutputStream fos;
private File file;
DataInputStream dis;
DataOutputStream dos;
BufferedInputStream bis;
BufferedOutputStream bos;
long length;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewOne = (TextView) findViewById(R.id.textView1);
buttonOne = (Button) findViewById(R.id.button1);
buttonOne.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Thread myThread = new Thread(MainActivity.this);
myThread.start();
}
});
} // oncreate
@Override
public void run() {
MainActivity.this.runOnUiThread(new Runnable(){
@Override
public void run() {
textViewOne.setText("run method started");
}
});
try {
socket = new Socket(InetAddress.getByName(serverIP), 6789);
if (socket == null) {
return;
} else {
MainActivity.this.runOnUiThread(new Runnable(){
@Override
public void run() {
textViewOne.setText("connected");
}
});
}
file = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "transfer.pdf");
length = file.length();
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
bos = new BufferedOutputStream(socket.getOutputStream());
dos = new DataOutputStream(bos);
dos.writeInt((int) length); // sends the length as number bytes is file size
int count = 0;
byte[] buffer = new byte[(int) length];
while ((count = bis.read(buffer)) > 0)
{
bos.write(buffer, 0, count);
}
bos.flush();
bis.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} // mainactivity
答案 0 :(得分:2)
这是问题,我相信。
int bytesRemaining = fileSizeFromClient = totalBytesRead;
这是两个分配,因此您立即将{0}分配给fileSizeFromClient
并退出循环。
你的意思是:
int bytesRemaining = fileSizeFromClient - totalBytesRead;
这是一个相当微妙的错字,你不幸的是它仍然是一个错字导致有效的代码:(
鉴于您无论如何都要立即关闭套接字,但不清楚为什么要先发送文件大小。如果您在客户端和服务器上只有相同的“从输入流复制到输出流,直到输入用完数据”,那么您的代码可能会更简单,只需从FileInputStream
到{{1客户端的Socket
和服务器上的OutputStream
的{{1}}到Socket
(可能带有缓冲包装器)。
我还建议关闭所有流 - 如果你使用的是Java 7,你只需使用try-with-resources语句即可;在早期版本中,您应该关闭InputStream
块中的流。
答案 1 :(得分:0)
- 通过经验法则,始终在写入/读取之后关闭Streams 。
- 在服务器端关闭流。
- 将Socket
与InputStream
和Scanner
一起使用,以便在套接字之间轻松传输数据。 (这就是我的感受,试验插座。)