本人编程新手,要求用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这样的框架来做,会简单很多。