❶ java中如何实现从客户端发送文件到服务器端
服务器端源码:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* 文件名:ServerReceive.java
* 实现功能:作为服务器接收客户端发送的文件
*
* 具体实现过程:
* 1、建立SocketServer,等待客户端的连接
* 2、当有客户端连接的时候,按照双方的约定,这时要读取一行数据
* 其中保存客户端要发送的文件名和文件大小信息
* 3、根据文件名在本地创建文件,并建立好流通信
* 4、循环接收数据包,将数据包写入文件
* 5、当接收数据的长度等于提前文件发过来的文件长度,即表示文件接收完毕,关闭文件
* 6、文件接收工作结束
public class ServerReceive {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
ServerSocket ss = null;
Socket s = null;
/**定义用于在接收后在本地创建的文件对象和文件输出流对象*/
File file = null;
FileOutputStream fos = null;
/**定义输入流,使用socket的inputStream对数据包进行输入*/
InputStream is = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**用来接收文件发送请求的字符串*/
String comm = null;
/**建立socekt通信,等待服务器进行连接*/
try {
ss = new ServerSocket(4004);
s = ss.accept();
} catch (IOException e) {
e.printStackTrace();
}
/**读取一行客户端发送过来的约定信息*/
try {
InputStreamReader isr = new InputStreamReader(s.getInputStream());
BufferedReader br = new BufferedReader(isr);
comm = br.readLine();
} catch (IOException e) {
System.out.println("服务器与客户端断开连接");
}
/**开始解析客户端发送过来的请求命令*/
int index = comm.indexOf("/#");
/**判断协议是否为发送文件的协议*/
String xieyi = comm.substring(0, index);
if(!xieyi.equals("111")){
System.out.println("服务器收到的协议码不正确");
return;
}
/**解析出文件的名字和大小*/
comm = comm.substring(index + 2);
index = comm.indexOf("/#");
String filename = comm.substring(0, index).trim();
String filesize = comm.substring(index + 2).trim();
/**创建空文件,用来进行接收文件*/
file = new File(filename);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("服务器端创建文件失败");
}
}else{
/**在此也可以询问是否覆盖*/
System.out.println("本路径已存在相同文件,进行覆盖");
}
/**【以上就是客户端代码中写到的服务器的准备部分】*/
/**
* 服务器接收文件的关键代码*/
try {
/**将文件包装到文件输出流对象中*/
fos = new FileOutputStream(file);
long file_size = Long.parseLong(filesize);
is = s.getInputStream();
/**size为每次接收数据包的长度*/
int size = 0;
/**count用来记录已接收到文件的长度*/
long count = 0;
/**使用while循环接收数据包*/
while(count < file_size){
/**从输入流中读取一个数据包*/
size = is.read(buffer);
/**将刚刚读取的数据包写到本地文件中去*/
fos.write(buffer, 0, size);
fos.flush();
/**将已接收到文件的长度+size*/
count += size;
System.out.println("服务器端接收到数据包,大小为" + size);
}
} catch (FileNotFoundException e) {
System.out.println("服务器写文件失败");
} catch (IOException e) {
System.out.println("服务器:客户端断开连接");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ServerReceive
客户端源码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
*
* 文件名:ClientSend.java
* 实现功能:作为客户端向服务器发送一个文件
*
* 具体实现过程:
* 1、建立与服务器端的连接,IP:127.0.0.1, port:4004
* 2、将文件的名字和大小通过自定义的文件传输协议,发送到服务器
* 3、循环读取本地文件,将文件打包发送到数据输出流中
* 4、关闭文件,结束传输
*
* */
public class ClientSend {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
Socket s = null;
/**定义文件对象,即为要发送的文件
* 如果使用绝对路径,不要忘记使用'/'和'\'的区别
* 具体区别,请读者自行查询
* */
File sendfile = new File("API.CHM");
/**定义文件输入流,用来打开、读取即将要发送的文件*/
FileInputStream fis = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**定义输出流,使用socket的outputStream对数据包进行输出*/
OutputStream os = null;
/**检查要发送的文件是否存在*/
if(!sendfile.exists()){
System.out.println("客户端:要发送的文件不存在");
return;
}
/**与服务器建立连接*/
try {
s = new Socket("127.0.0.1", 4004);
}catch (IOException e) {
System.out.println("未连接到服务器");
}
/**用文件对象初始化fis对象
* 以便于可以提取出文件的大小
* */
try {
fis = new FileInputStream(sendfile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
/**首先先向服务器发送关于文件的信息,以便于服务器进行接收的相关准备工作
* 具体的准备工作,请查看服务器代码。
*
* 发送的内容包括:发送文件协议码(此处为111)/#文件名(带后缀名)/#文件大小
* */
try {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
ps.flush();
} catch (IOException e) {
System.out.println("服务器连接中断");
}
/**
* 此处睡眠2s,等待服务器把相关的工作准备好
* 也是为了保证网络的延迟
* 读者可自行选择添加此代码
* */
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
/**之前的准备工作结束之后
* 下面就是文件传输的关键代码
* */
try {
/**获取socket的OutputStream,以便向其中写入数据包*/
os = s.getOutputStream();
/** size 用来记录每次读取文件的大小*/
int size = 0;
/**使用while循环读取文件,直到文件读取结束*/
while((size = fis.read(buffer)) != -1){
System.out.println("客户端发送数据包,大小为" + size);
/**向输出流中写入刚刚读到的数据包*/
os.write(buffer, 0, size);
/**刷新一下*/
os.flush();
}
} catch (FileNotFoundException e) {
System.out.println("客户端读取文件出错");
} catch (IOException e) {
System.out.println("客户端输出文件出错");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fis != null)
fis.close();
} catch (IOException e) {
System.out.println("客户端文件关闭出错");
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ClientSend
❷ 在java中怎么将一组数据从客户端发送到服务器端
通过反射!
下面是一个服务器与客户端信息交互的例子:
反射API介绍
4.Java Socket编程 TCP 协议编程
1) TCP工作模型: 先找
堂(主机/IP), 到食堂以后找窗口
(Socket/套接字 端口号), 服务员等待连接,客户向服务员发起连接
连接以后, 一个窗口可以为每个客户安排一个服务员(线程)提供服务,
每个服务过程可以双向交流通讯(流), 通讯完成后要关闭连接.
5. TCP 服务端编程(食堂)(java.io.*,java.net.*,java.lang.*)
1) 创建ServerSocket实例绑定一个服务端口(Socket/套接字 端口号)
2) 开始ServerSocket实例 的监听, 等待客户端的连接
3) 如果有客户连接进来, 就获得了客户的套接字(Socket)实例
客户的套接字(Socket)实例中包括与客户端建立的连接流
4) 为这个客户(Socket) 创建一个服务线程, 提供服务(run方法)
5) 继续等待下一个连接, 返回到2)
6) 服务线程 完成通讯服务过程
7) 端口号: 0~65535, 1K以下留给系统使用
6. TCP 客户端编程
1) 创建Socket 实例, 连接到服务器端, 成功创建s就表示连接到了
服务器
Socket s = new Socket("host", port)
2) 客户端 Socket 与服务器端 Socket 对应, 都包含输入, 输出流
客户端的s.getInputStream() 连接于服务器s.getOutputStream()
客户端的s.getOutputStream()连接于服务器s.getInputStream()
3) 使用线程处理 网络流
7. Java 反射
1) 反射是Java自我管理(类, 对象)的机制
2) * 可以通过反射机制发现对象的类型 发现类型的方法/属性/构造器
3) * Java 反射 可以创建对象 并 访问任意对象方法和属性等
4) Class 加载
类加载到内存: java 将磁盘类文件加载到内存中,为一个对象(实例)
这个对象是Class的实例, 也就是 这些对象都是Class实例
5)Class 实例代表Java中类型, 基本类型的类型: int.class, long.class
类类型 Class 实例获得如下:
Class cls = String.class;
Class cls = Class.forName("java.lang.String");
Class cls = "abc".getClass();
以上方法获得cls 是同一个对象, 就是String 类内存加载的结果
package javase2.day06.ftp;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Scanner;/** * ftp 客户端 可以使用命令 ls pwd get */public class FtpClient { public static void main(String[] args) throws IOException{ FtpClient client = new FtpClient(); client.open(); } public void open() throws IOException{ Socket s = new Socket("localhost", 9000); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); //处理客户端对服务器的请求 new RequestProcess(out).start(); //处理服务器的反馈信息 new ResponseProcess(in).start(); }//处理客户端对服务器的请求 class RequestProcess extends Thread{ OutputStream out; public RequestProcess(OutputStream out) { this.out = out; } public void run() { try{ Scanner sc = new Scanner(System.in); while(true){ String s = sc.nextLine(); IOUtils.println(out, s); if(s.equals("bye")){ System.exit(0); } } }catch(IOException e){ e.printStackTrace(); } } } class ResponseProcess extends Thread{ InputStream in; public ResponseProcess(InputStream in) { this.in = in; } public void run() { try{ while(true){ String header = IOUtils.readLine(in); if(header.startsWith("text,")){ show(header,in); }else if(header.startsWith("file,")){ save(header, in); } } }catch(IOException e){ e.printStackTrace(); } } } public void show(String header, InputStream in) throws IOException { int n = Integer.parseInt(header.split(",")[1]); for(int i=0; i<n; i++){ String s = IOUtils.readLine(in); System.out.println(s); } } public void save(String header, InputStream in) throws IOException{ File dir = new File("ftp"); if(!dir.exists()){ dir.mkdir(); } //header: file,10,filename String[] data = header.split(","); long length = Long.parseLong(data[1]); String filename = data[2]; File file = new File(dir, filename); BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(file)); for(long i=0; i<length; i++){ int b = in.read(); out.write(b); } out.close(); } }-----------------------------------package javase2.day06.ftp;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * 模拟FTP服务器, 支持命令pwd,ls,get file * * 协议: type,length,value TLV格式 * * 文本: text,5\nline1\nline2\nline3\nline4\nline5\n * 文件: file,4,filename\n 41 42 43 44 * * text,5\nline1\nline2\nline3\nline4\nline5\nfile,4,filename\n 41 42 43 44 */public class FtpServer { public static void main(String[] args) throws IOException{ FtpServer server = new FtpServer(); server.start(); } public void start() throws IOException{ ServerSocket ss = new ServerSocket(9000); while(true){ Socket s = ss.accept(); new Agent(s).start(); } } class Agent extends Thread{ Socket s; public Agent(Socket s) { this.s = s; } public void run() { try{ InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); //向客户端发送, 先发协议头,再发送文本行 out.write("text,1\n".getBytes());//协议头 //发送消息内容, 一行文本消息 out.write("欢迎使用FTP演示服务器!\n".getBytes()); out.flush(); while(true){ //读取客户端发送到命令 String cmd = IOUtils.readLine(in).trim(); if("pwd".equals(cmd)){//显示当前目录 pwd(out); }else if("ls".equals(cmd)){ ls(out); }else if(cmd.startsWith("get ")){ get(cmd, out); }else if("bye".equalsIgnoreCase(cmd)){ IOUtils.println(out, "text,1"); IOUtils.println(out, "Bye, Bye!"); s.close(); }else{ out.write("text,1\n".getBytes());//协议头 out.write("只支持pwd,ls,get,bye!\n".getBytes()); out.flush(); } } }catch(IOException e){ e.printStackTrace(); } } } public void pwd(OutputStream out) throws IOException{ File dir = new File("."); IOUtils.println(out, "text,1"); IOUtils.println(out, dir.getCanonicalPath()); } public void ls(OutputStream out) throws IOException{ File dir = new File("."); File[] files = dir.listFiles(); IOUtils.println(out, "text,"+files.length); for (File f : files) { if(f.isDirectory()){ IOUtils.println(out, "["+f.getName()+"]"); }else{ IOUtils.println(out, f.getName()); } } } public void get(String cmd, OutputStream out) throws IOException{ //cmd="get filename" String name = cmd.split("\\s+")[1]; File file = new File(name); if(! file.exists()){ IOUtils.println(out, "text,1"); IOUtils.println(out, "没有文件呀!"+name); return; } //文件协议头: IOUtils.println(out, "file,"+file.length()+","+name); FileInputStream in = new FileInputStream(file); IOUtils.cp(in, out); out.flush(); in.close(); IOUtils.println(out, "text,1"); IOUtils.println(out, "发送成功:"+name); }}