一、程序功能简介

完成客户端和服务器端文件的传输,客户端向服务器端上传文件,服务器端存在固定的路径下面;客户端从服务器端下载文件,并保存在固定的路径下面。

二、程序用到的知识点

socket连接,线程创建,流的处理,字符串处理,java界面

1.socket连接服务器端

ServerSocket ssocket  =  new ServerSocket(3000);//侦听端口
Socket socket = ssocket.accept();//如果有人连接 这条代码便运行下去。

   socket连接客户端

Socket socket = new Socket(ip,port);//客户端连接服务器,要提供服务器的ip 和端口

 2.流的处理

当数据流在socket中进行传输时,要把它们转成二进制流进行传输。

从本地读取文件流

DataInputStream is = new DataInputStream(new BufferInputStream(new FileInputStream(filepath)));

 从外部读取传输过来的数据流

DataInputStream io = new DataInputStream(socket.getInputStream());

向本地输出文件流

DataOutputStream os = new DataOutputStream(new BufferOutputStream(new FileOutputStream(filepath)));

 向外部输出数据流

DataOutputStream out = new DataOutputStream(socket.getOutputStream());

 3.线程的创建方法

new Thread(){
public void run(){
//写入在线程中要执行的代码;
}
}.start();

 4.字符串的处理

If(string.indexOf('@')!=-1){
//判断字符串中是否含有“@”字符
subString(0,string.indexOf("@"));//截取@之前的字符串
subString(string.indexOf("@")+1,string.length());//截取@之后的字符串 length 
要比最后一个字符的索引大1}

 5.java界面

注意现将成员变量列出,静态变量可供全局访问,然后写构造函数,讲成员变量进行布局排列,编辑,添加事件,最后在主函数中调用构造函数,进行显示。大小固定设置setSize(),位置固定设置setBounds();pack();是根据内容自己调整大小,布局分为flowlayout布局 BorderLayout布局GridLayout布局

 

三、程序功能模块及代码

客户端界面

import java.awt.FlowLayout;
import java.awt.event.*;
import java.io.IOException;
import java.net.UnknownHostException;
import javax.swing.*;

public class frame  extends JFrame{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	JLabel lbl_up = new JLabel("上传");                     //定义成员变量
	JTextField textfield1 = new JTextField("请选择上传文件...        ");
	JButton btn_shangchuan  = new JButton("开始上传");
	
	JLabel  lbl_down = new JLabel("下载");
	JTextField textfield2 = new JTextField("请输入下载地址...       ");
	JButton btn_xiazai = new JButton("开始下载");
	static JTextArea textarea = new JTextArea(15,25);
	
    ActionListener downloadListener=new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent arg0) {
			// TODO Auto-generated method stub
			String url = textfield2.getText();
			if(url.indexOf("@")!=-1){
			String ip = url.substring(0, url.indexOf("@"));
			String path = url.substring(url.indexOf("@")+1,url.length());
			new Download(ip,path,"C:\\download");
			}
		}
	};
	
	ActionListener uploadListener=new ActionListener(){
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			
				try {
					
					String url = textfield1.getText();
					System.out.println(url);
					if(url.indexOf("@")!=-1){
					String ip = url.substring(0,url.indexOf("@"));
					String path = url.substring(url.indexOf('@')+1,url.length());
					System.out.println(ip);
					System.out.println(path);
					new upload(path,ip,3000);
					
					textarea.setText("文件已上传成功!");
					}else{
						textarea.setText("请输入正确下载地址,格式为:'ip@c:\\..'");
					}
					System.out.println("c:\\abc");
					
				} catch (UnknownHostException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
		
		
	}; 
	public frame(){                               //构造函数
		textarea.setLineWrap(true);
		 setSize(300, 400);   //设置大小
		 setResizable(false); //固定大小,不能改变
		setLayout(new FlowLayout(0));//设置布局为flowlayout类型
		textfield1.setEditable(true);
		btn_shangchuan.addActionListener(uploadListener);
		btn_xiazai.addActionListener(downloadListener);     

		 JPanel panel_up =new JPanel();
		 JPanel panel_down = new JPanel();
		 JPanel panel_state = new JPanel();
		 panel_up.add(lbl_up);
		 panel_up.add(textfield1);
		 panel_up.add(btn_shangchuan);
		 panel_down.add(lbl_down);
		 panel_down.add(textfield2);
		 panel_down.add(btn_xiazai);
		 panel_state.add(textarea);
		 
		 
		 getContentPane().add(panel_up); //把控件放到一个panel中,然后服从flowlayout布局
		 getContentPane().add(panel_down);
		 getContentPane().add(panel_state);

		 }
		 

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		frame fm = new  frame();
		fm.setDefaultCloseOperation(EXIT_ON_CLOSE); //当界面被关闭时,程序退出。
		fm.setVisible(true);                         //显示界面
		

	}

}

 

 

客户端上传部分

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class upload {

	private void socket(String filepath,String address, int port) throws UnknownHostException, IOException {
      	Socket sock = new Socket(address, port);
		DataOutputStream os = null;
		DataInputStream is = null;
		os = new DataOutputStream(sock.getOutputStream());
		is = new DataInputStream(new BufferedInputStream(new FileInputStream(filepath)));
		File file = new File(filepath);
		System.out.println("发送前;"+file.getName());
		os.writeByte(0);//标志上传 与下载区分;
		os.writeUTF(file.getName());  //用这种方法写出去 然后再用这种方法读粗来。。。
		System.out.println(file.getName());
		os.writeLong(file.length());
		
		int bufferSize = 8192;
		byte[] bt = new byte[bufferSize];

		while(true){
			System.out.println("文件在传输中");
			
			int read = 0;
			if(is != null){
			read = is.read(bt);
			}
			if(read !=-1){
				os.write(bt,0,read);
			}
			if(read ==-1){
				break;
			}
		}
		is.close();
		os.flush();
		sock.close();
		System.out.println("\n文件已上传成功!");
	}
	
	
	public upload(String filepath,String address, int port) throws UnknownHostException, IOException{
		
		socket(filepath,address, port);
		
		
	}
}

 

客户端下载部分

import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Download {

	public Download(String ip, String path,String savepath) {
		// TODO Auto-generated constructor stub
		
		try {
			Socket sock  = new Socket(ip,3000);
	        DataOutputStream os = new DataOutputStream(sock.getOutputStream());
	        DataInputStream is = new DataInputStream(sock.getInputStream());
	        os.writeByte(1);    
	        os.writeUTF(path);
	        String fileName = is.readUTF();
	        savepath += "\\"+fileName;
	        Long fileLength = is.readLong();
	        int bufferSize = 8192;
	        byte[] bf = new byte[bufferSize];
	        DataOutputStream fsv = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savepath)));
	        while(true){
	        	if(fileLength>0){
	        		is.read(bf);
	        		fsv.write(bf);
                    fileLength -= bufferSize;	        		
	        		
	        		
	        	}else{
	        		break;
	        	}
	        	
	        }
	        fsv.flush();
	        fsv.close();
	        is.close();
	        os.close();
	        sock.close();
	        frame.textarea.append("文件已下载成功!保存路径为"+savepath);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

 

服务器端

界面

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextArea;
public class frame extends JFrame{
	private static final long serialVersionUID = 1L;
	 static JFrame frame =new JFrame("Server");
	 static JButton button = new JButton("开始连接");
	 static JTextArea textarea = new JTextArea(15,20);
	 
	 public frame(){
		 frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		 frame.setLayout(new BorderLayout());
		 frame.setBounds(700, 200, 350, 400);  //固定界面显示位置
		 button.setSize(80,60);
		 button.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				System.out.println("等待连接");
		        new server();
			
			}
		});

		
		 textarea.setLineWrap(true);
		 frame.getContentPane().add(button,BorderLayout.NORTH);
		 frame.getContentPane().add(textarea,BorderLayout.SOUTH);
		 
	 }
	
	public static void main(String[] args) {
      new  frame();
	 frame.setVisible(true);

	}	

}

 服务器端功能

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class server {
	String savepath = null;
	ServerSocket serverSocket;
	Socket socket;
	InputStream inputStream;
	OutputStream outputStream;
	int bufferSize = 8192;
public  server(){
	System.out.println("进来了");
	System.out.println(":wtf");
	try {
		serverSocket = new ServerSocket(3000);
	} catch (IOException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	}
	new Thread(){
		
	  public void	run(){
		  while(true){
		  try {
                frame.textarea.append("\n等待连接..");
				Socket ssock = serverSocket.accept();
				frame.textarea.append("\n连接已创建");
				System.out.println("连接已创建");
				DataInputStream io = new DataInputStream(new BufferedInputStream(ssock.getInputStream())); 
				
				if(io.readByte()==0){
				
				String fileName = io.readUTF();  //这是一个神奇的方法  用什么方法传 就会用什么方法 读粗来。。。
			    Long length  = io.readLong();
			    savepath = "c:\\bcd\\"+fileName;
				System.out.println(fileName);
				System.out.println(length);
				byte[] buf = new byte[bufferSize];

					DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savepath)));
					
				while(true){
					 int read = 0;
					if(length > 0){
						read = io.read(buf);
						length -= bufferSize;
						out.write(buf,0,read);
					}
					else
					{
                       io.close();	
                       out.close();
						break;
					}
					
				}
				System.out.println("文件已接收成功!");
				frame.textarea.append("\n 文件已上传成功!保存路径为"+savepath);
				}else{                                //下载功能
					String path = io.readUTF();
					System.out.println(path);
				    File file = new File(path);
				    DataOutputStream os = new DataOutputStream(ssock.getOutputStream());
					DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
			     
					os.writeUTF(file.getName());
					os.writeLong(file.length());
					byte[] buf  = new byte[bufferSize];
					
					while(true){
                                          int read = 0;
                                          if(is!=null){
  	                                                         read = is.read(buf);
  	                                                         if(read !=-1){
  	                                                         os.write(buf,0,read);
  	                                                         }else{
  	                                                             is.close();
  	                                            	             os.flush();
  	                                            	             os.close();
  	                                            	             System.out.println("资源下载成功");
  	                                            	             frame.textarea.append("\n资源被下载");
					                                              break;
  	                                                                     }
                                            }else 
                                            {
                                                System.out.println("所找资源不存在");
                                            	break;
                                            }
                                          }
				}	
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			
	  }
	  
	}.start();

	}
}

四、程序有待完善的部分

代码健壮性不强,上传下载文件必须是已知路径存在,否则程序不能继续运行下去,在上传时如果能写成浏览本地文件的功能就好了,在服务器端有固定的存储上传文件的路径如果路径不存在,可以自行创建路径就好了;下载功能同样是这样,但是浏览服务器上的文件似乎有些难度,进行本地存储是跟服务器端上传文件存储一样的。