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