问题描述
本人编程新手,要求用java写一个tcp文件服务器,客户端向服务器端发送请求,下载服务器端的文件。我出现的问题是:客户端从服务器端下载到的文件大小不一致,而且下载到的文件也带不开,真诚请教解决办法。//客户端代码import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.Socket;import java.util.Scanner;public class SendFileClient{ public static void main( String[] args ) throws IOException { // TODO Auto-generated method stub System.out.println( "This is client" ); byte[] buf = new byte[1024]; System.out.println("Please input the Ip Address that you connect");//Create the scanner s1 to let user input the server IP address Scanner s1 = new Scanner(System.in); String ip = s1.nextLine(); System.out.println("Please input the port");//Create the scanner s2 to let user input the server port Scanner s2 = new Scanner(System.in); String portStr = s2.nextLine();//Convert the String portStr to integer int port = Integer.parseInt(portStr); try { // Create the socket Socket s = new Socket(); s.connect ( new InetSocketAddress (ip,port ));//Create the outstream OutputStream os = s.getOutputStream( );//Create the inputstream InputStream is = s.getInputStream( );//Read the buf though the inputstream int len = is.read( buf );//Print out the data by converting it to a String System.out.println( new String( buf, 0, len ) ); System.out.println("Please input the request");//Create scanner s3 to Let the user input the request//The request format has to be:Send filename Scanner s3 = new Scanner(System.in); String req = s3.nextLine(); os.write( req.getBytes( ) );//Read the data to buf though the inputstream int len2 = is.read(buf); String file = new String(buf,0,len2); System.out.println("Wait...");//Create the dataoutputstream for receiving the file DataOutputStream fos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); byte[] buff = new byte[1024];//Receive the file, write it out. int data; while ( -1 != ( data = is.read(buff) ) ) { fos.write( buff ); } System.out.println("nFile has been received successfully.");fos.flush();fos.close();//Close the outputstreamos.flush(); os.close();//Close the inputstream is.close();//Close the socket s.close( ); } catch ( Exception ex ) { ex.printStackTrace(); } } }import java.net.*;import java.io.*;//服务器端代码public class SendFileSocket extends Thread{ /** * @param args */ public static void main( String[] args ) {//Start the server server( ); }//Set the Server port =10000 private static final int PORT = 10000; private Socket s; public SendFileSocket( Socket s ) {//Create the socket object this.s = s; } public void run() { try {//Create the outputstream OutputStream os = s.getOutputStream( );//Create the inputstream InputStream is = s.getInputStream( ); os.write( "Hello,welcome you!".getBytes( ) );//Define the data byte as buf byte[] buf = new byte[10240]; while ( true ) {//Read the buf though the inputstream int len = is.read( buf ); String revStr = new String( buf, 0, len );//Print out the request information from the client System.out.println( "This client wants to "+revStr ); String fileName;//The requet should starts with Send if ( revStr.startsWith( "Send " )) {//Get the file name from the request by using//The method getFileName fileName = getFileName( revStr );//Print out the filename System.out.println( "The file name is :"+fileName);//Write out the filename though the outputstream os.write(fileName.getBytes()); System.out.println("Start to send file " +fileName); String filePath = "C:/"; String file = (filePath+fileName);//Combine the filepath and the filename File fi = new File(file); //Declare a datainputstream DataInputStream fins = new DataInputStream( new BufferedInputStream(new FileInputStream(file))); DataOutputStream ps = new DataOutputStream(s.getOutputStream());//Start to read the data from the file byte[] buff = new byte[10240]; int data; while ( -1 != ( data = fins.read(buff) ) ) { //send the file data to the client ps.write( buff ); } System.out.println("Transfer complete.");ps.flush();ps.close(); break; } else{ System.out.println("Request is wrong"); System.exit(0); } }os.flush();//Close the outputstream os.close( );//Close the inputstream is.close( );//Close the socket s.close( ); } catch ( Exception e ) {//Catch the exception e.printStackTrace( ); } } /* * Function:Get the filename from the request which is sent from the client * param:The request from the client has to start with"Send" * Return: The filename */ private String getFileName( String revStr ) { String fileName; fileName = revStr.substring( 4 ); while ( fileName.startsWith( " " ) ) { fileName = fileName.substring( 1 ); } return fileName; } public static void server() { System.out.println( "This is server" ); try { ServerSocket ss = new ServerSocket( PORT ); int count = 0; while ( true ) {//Create a socket for waiting for the client connect Socket s = ss.accept( );//Count the client and print out count++ ; System.out.println( "This is the " + count + "'st client connetion!" );//Start new thread for this socket new Thread(new SendFileSocket(s)).start(); } } catch ( Exception ex )//Catch the exception { ex.printStackTrace( ); } }}
解决方案
byte[] buff = new byte[1024]; //Receive the file, write it out. int data; while ( -1 != ( data = is.read(buff) ) ) { fos.write( buff,0,data ); } 你这里读到的不一定就是1024,特别是最后一次,不太可能是1024的整数,所以你写出的时候,应该以读到的为准来写出,而不是把整个buff都写出
解决方案二:
建议采用mina或者netty这样的框架来做,会简单很多。
解决方案三:
1.你服务器端while (-1 != (data = fins.read(buff))) {// send the file data to the client// 这种表示将buff 全部发送过去,如果buff 不是满的,会多出限制。// 比如你缓冲区1024*1024 1M,但是你发送1KB 的文件,那么也会导致客户端接受1M的数/据,多出来的默认是0,表示是byte 空的ps.write(buff);// 正确的做法应该是这样,获取多少发多少,两边这样改了就OK了ps.write(buff,0,data);} 2.你客户端也可以采取同样的方式,你也可以采用自带的缓冲流:public BufferedInputStream(InputStream in, int size) 类似的,多看看API 很多的。3.一般网络传文件,最好先发送一段数据,表示文件的大小,先接受,然后在读取文件流,比较大小,确定文件大小是否一致。4.如果文件比较大,或者比较多,你可以采用多线程,但是每个线程你最好都监听一下获取了多少字节,然后再合并到一起,等等措施。自学,可以多尝试哦~.~
解决方案四:
服务器端代码第36行和66行byte[] buf = new byte[10240];10240改为1024