一、程序功能简介
完成客户端和服务器端文件的传输,客户端向服务器端上传文件,服务器端存在固定的路径下面;客户端从服务器端下载文件,并保存在固定的路径下面。
二、程序用到的知识点
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(); } }
四、程序有待完善的部分
代码健壮性不强,上传下载文件必须是已知路径存在,否则程序不能继续运行下去,在上传时如果能写成浏览本地文件的功能就好了,在服务器端有固定的存储上传文件的路径如果路径不存在,可以自行创建路径就好了;下载功能同样是这样,但是浏览服务器上的文件似乎有些难度,进行本地存储是跟服务器端上传文件存储一样的。