使用socket编程实现一个简单的文件服务器。客户端程序实现put功能(将一个文件从本地传到文件服务器)和get功能(从文件服务器取一远程文件存为本地文件)。客户端和文件服务器不在同一台机器上。
put [-h hostname] [-p portname] local_filenameremote_filename
get [-h hostname] [-p portname] remote_filenamelocal_filename
程序如下:
客户端Client.java
package com.cn.gao;
import java.net.*;
import java.io.*;
/**
*
* 用Socket实现文件服务器的客户端
* 包含发送文件和接收文件功能
*
*/
public class Client {
private Socket client;
private boolean connected;
//构造方法
public Client(String host,int port){
try {
//创建Socket对象
client = new Socket(host,port);
System.out.println("服务器连接成功!");
this.connected = true;
} catch (UnknownHostException e) {
System.out.println("无法解析的主机!");
this.connected = false;
} catch (IOException e) {
System.out.println("服务器连接失败!");
this.connected = false;
closeSocket();
}
}
//判断是否连接成功
public boolean isConnected(){
return connected;
}
//设置连接状态
public void setConnected(boolean connected){
this.connected = connected;
}
/**
* 发送文件方法
* @param localFileName 本地文件的全路径名
* @param remoteFileName 远程文件的名称
*/
public void sendFile(String localFileName, String remoteFileName){
DataOutputStream dos = null; //写Socket的输出流
DataInputStream dis = null; //读取本地文件的输入流
if(client==null) return;
File file = new File(localFileName);
//检查文件是否存在
if(!file.exists()){
System.out.println("本地文件不存在,请查看文件名是否写错!");
this.connected = false;
this.closeSocket();
return;
}
try {
//初始化本地文件读取流
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
//将指令和文件发送到Socket的输出流中
dos = new DataOutputStream(client.getOutputStream());
//将远程文件名发送出去
// System.out.println(remoteFileName);
dos.writeUTF("put "+remoteFileName);
//清空缓存,将文件名发送出去
dos.flush();
//开始发送文件
int bufferSize = 10240;
byte[] buf = new byte[bufferSize];
int num =0;
while((num=dis.read(buf))!=-1){
dos.write(buf, 0, num);
}
dos.flush();
System.out.println("文件发送成功!");
} catch (IOException e) {
System.out.println("文件传输错误!");
closeSocket();
} finally{
try {
dis.close();
dos.close();
} catch (IOException e) {
System.out.println("输入输出错误!");
}
}
}
/**
* 接收文件方法
* @param remoteFileName 本地文件的全路径名
* @param localFileName 远程文件的名称
*/
public void receiveFile(String remoteFileName, String localFileName){
DataOutputStream dos = null; //写Scoket的输出流
DataInputStream dis = null; //读Socket的输入流
DataOutputStream localdos = null; //写本地文件的输出流
if(client==null) return;
try {
localdos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(localFileName)));
//将指令和文件名发送到Socket的输出流中
dos = new DataOutputStream(client.getOutputStream());
//将远程文件名发送出去
dos.writeUTF("get "+remoteFileName);
dos.flush();
//开始接收文件
dis = new DataInputStream(new BufferedInputStream(client.getInputStream()));
int bufferSize = 10240;
byte[] buf = new byte[bufferSize];
int num = 0;
while((num=dis.read(buf))!=-1){
localdos.write(buf, 0, num);
}
localdos.flush();
System.out.println("数据接收成功!");
} catch (FileNotFoundException e) {
System.out.println("文件没有找到!");
closeSocket();
} catch (IOException e) {
System.out.println("文件传输错误!");
} finally {
try {
dos.close();
localdos.close();
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//关闭端口
public void closeSocket(){
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 主方法调用上述方法
* @param args
* 将本地文件上传到远程服务器
* put[-h hostname][-p portname]local_filename remote_filename
* 从远程服务器上下载文件
* get[-h hostname][-p portname]remote_filename local_filename
*/
public static void main(String[] args){
//服务器默认端口为8888
if(args.length!=7){
System.out.println("参数数目不正确!");
return;
}
String hostName = args[2];
int port = 0;
String localFileName = "";
String remoteFileName = "";
Client client = null;
try {
port = Integer.parseInt(args[4]);
} catch (NumberFormatException e) {
System.out.println("端口号输出格式错误!");
return;
}
if(args[0].equals("put")){
//上传文件
client = new Client(hostName,port);
localFileName = args[5];
remoteFileName = args[6];
// System.out.println(remoteFileName);
if(client.isConnected()){
client.sendFile(localFileName, remoteFileName);
client.closeSocket();
}
}else if(args[0].equals("get")){
//下载文件
client = new Client(hostName,port);
localFileName = args[6];
remoteFileName = args[5];
if(client.isConnected()){
client.receiveFile(remoteFileName, localFileName);
client.closeSocket();
}
}else{
System.out.println("命令输入不正确,正确命令格式如下:");
System.out.println("put -h hostname -p portname local_filename remote_filename");
System.out.println("get -h hostname -p portname remote_filename local_filename");
}
}
}
服务器端Server.java
package com.cn.gao;
import java.io.*;
import java.net.*;
/**
* 实现服务器端
* 用于接收上传的数据和供客户端下载数据
* @author DELL
*
*/
public class Server {
private int port;
private String host;
private String dirPath;
private static ServerSocket server; public Server(int port,String dirPath){
this.port = port;
this.dirPath = dirPath;
this.server = null;
} public void run(){
if(server==null){
try {
server = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("服务已启动...");
while(true){
try {
//通过ServerSocket的accept方法建立连接,并获取客户端的Socket对象
Socket client = server.accept();
if(client==null) continue;
new SocketConnection(client,this.dirPath).run();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 实现服务器端的数据传输
* @author DELL
*
*/
public class SocketConnection extends Thread{
private Socket client;
private String filePath; public SocketConnection(Socket client, String filePath){
this.client = client;
this.filePath = filePath;
} public void run(){
if(client==null) return;
DataInputStream in= null; //读取Socket的输入流
DataOutputStream dos = null; //写文件的输出流
DataOutputStream out = null; //写Socket的输出流
DataInputStream dis = null; //读文件的输入流
try {
//访问Scoket对象的getInputStream方法取得客户端发送过来的数据流
in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
String recvInfo = in.readUTF(); //取得附带的指令及文件名
// System.out.println(recvInfo);
String[] info = recvInfo.split(" ");
String fileName = info[1]; //获取文件名
// System.out.println(fileName);
if(filePath.endsWith("/")==false&&filePath.endsWith("\\")==false){
filePath+="\\";
}
filePath += fileName;
if(info[0].equals("put")){
//从客户端上传到服务器
//开始接收文件
dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File(filePath))));
int bufferSize = 10240;
byte[] buf = new byte[bufferSize];
int num =0;
while((num=in.read(buf))!=-1){
dos.write(buf, 0, num);
}
dos.flush();
System.out.println("数据接收完毕!");
}else if(info[0].equals("get")){
//从服务器下载文件到客户端
dis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));
//开始发送文件
int bufferSize = 10240;
byte[] buf = new byte[bufferSize];
out = new DataOutputStream(client.getOutputStream());
int num =0;
while((num=dis.read(buf))!=-1){
out.write(buf, 0, num);
}
out.flush();
System.out.println("发送成功!");
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if(out!=null) out.close();
if(in!=null) in.close();
if(dos!=null) dos.close();
if(dis!=null) dis.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} public static void main(String[] args){
//设置服务器端口
int port = 8888;
//设置服务器文件存放位置
String dirPath = "D:\\FTPService\\";
new Server(port,dirPath).run();
}
}
参数输入方式示例
put -h 127.0.0.1 -p 8888 D:\\data.xls data.xls
get -h 127.0.0.1 -p 8888 data.xls D:\\data.xls