Java TCP文件服务器,下载到的文件和原文件大小不一致

本人编程新手,要求用java写一个tcp文件服务器,客户端向服务器端发送请求,下载服务器端的文件。我出现的问题是:客户端从服务器端下载到的文件大小不一致,而且下载到的文件也带不开,真诚请教解决办法。
[code="java"]
//客户端代码
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 outputstream
        os.flush();
        os.close();
        //Close the inputstream
        is.close();
        //Close the socket
        s.close( );
    } catch ( Exception ex )
    {
        ex.printStackTrace();
    }
}

}
[/code]

[code="java"]
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( );
    }
}

}

[/code]

[code="java"] byte[] buff = new byte[1024];

//Receive the file, write it out.

int data;

while ( -1 != ( data = is.read(buff) ) )

{

fos.write( buff,0,data );

}

[/code]
你这里读到的不一定就是1024,特别是最后一次,不太可能是1024的整数,所以你写出的时候,应该以读到的为准来写出,而不是把整个buff都写出

服务器端代码第36行和66行byte[] buf = new byte[10240];10240改为1024

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.如果文件比较大,或者比较多,你可以采用多线程,但是每个线程你最好都监听一下获取了多少字节,然后再合并到一起,等等措施。自学,可以多尝试哦~.~

建议采用mina或者netty这样的框架来做,会简单很多。