本文中的是使用TCP协议进行文件传输
Socket
套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。
信息与文件传输使用C/S(Client/Server)。
步骤
1、启动服务端,等待客户端连接。
2、启动客户端连接服务端。
3、传输数据。
4、关闭客户端。
5、关闭服务端。
代码
首先启动服务端
package priv.zb.socket;
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;
public class FileServer {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ServerSocket server = null;
Socket socket = null;
//向外界暴露一个端口9999的服务,默认IP为本机IP:127.0.0.1
server = new ServerSocket(9999);
//返回一个Socket对象
socket = server.accept();
/**
*
* 启动服务端之后,会在 server.accept(); 方法处等待客户端的
* 连接,当启动客户端连接上服务端之后走过此方法运行后面的代码。
*/
System.out.println("接收到客户端的连接");
//服务端向客户端发送消息 通过OutputStream
//发出信息使用输出流OutputStream,接收信息使用输入咯InputStream
OutputStream output = socket.getOutputStream();
//传输字符串
// byte[] bs = new byte[100];
// output.write("Hello".getBytes());
//传输文件
String filePath = "存放文件路径";
File file = new File(filePath );
byte[] fileBytes = new byte[100]; //定义文件每次发送大小
//读入到内存中,new 一个inputStream即可
//文件较大,不能一次性发送完毕,因此需要循环操作
InputStream fileIn = new FileInputStream(file);
int len = -1;
while((len = fileIn.read(fileBytes)) != -1) {
output.write(fileBytes, 0, len);
}
//接受客户端消息
// InputStream in = socket.getInputStream();
// in.read(bs);
// System.out.println("Server接收到信息:" + new String(bs));
System.out.println("发送成功");
output.close();
fileIn.close();
}
}
之后启动客户端
package priv.zb.socket;
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.net.UnknownHostException;
public class FileClient {
@SuppressWarnings("resource")
public static void main(String[] args) throws UnknownHostException, IOException {
//建立连接
//客户端访问服务端发布的服务
Socket socket = new Socket("192.168.0.108",9999);
//通过InputStream接收信息
InputStream input = socket.getInputStream();
byte[] fileBytes = new byte[100];
File file = new File("E:\\JAVA\\Java SE\\srcCopy.zip");
OutputStream output = new FileOutputStream(file);
int len = -1;
while( (len = input.read(fileBytes)) != -1) {
output.write(fileBytes, 0, len);
}
//客户端接收到信息返回一个标识
// byte[] bs = new byte[100];
// input.read(bs);
// System.out.println("Client 接收到消息:" + new String(bs));
//客户端向服务端发送一个消息
// OutputStream output = socket.getOutputStream();
// output.write("World".getBytes());
System.out.println("接收成功!!");
output.close();
input.close();
}
}
这个代码在客户端连接一次之后,服务端便会主动关闭。但是在实际的使用中一般不会只使用一次服务端,将会不断地重复连接服务端这一过程。因此使用while(true)死循环来保持服务端的始终开启,利用多线程来解决这一问题。
优化
使用多线程是在服务端
服务端
package priv.zb.socket.runable;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServer {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
//向外界暴露一个端口9999的服务,默认IP为本机IP:127.0.0.1
ServerSocket server = new ServerSocket(9999);
while(true) {
Socket socket = server.accept();
//使用构造方法传入一个Socket对象与下载线程保持关联
new Thread(new MyDownload(socket)).start();
//下载线程
/*
* MyDownload download = new MyDownload(socket);
* //Runnable变为Thered对象
* new Thread(download).start();
*/
}
}
}
下载线程:MyDownload.java
package priv.zb.socket.runable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class MyDownload implements Runnable {
//Mydownload.java与Server之间使用Socket对象联系
private Socket socket;
public MyDownload(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
//返回一个Socket对象
OutputStream output =null;
InputStream fileIn = null;
try {
System.out.println("接收到客户端的连接");
//服务端向客户端发送消息 通过OutputStream
File file = new File("E:\\JAVA\\Java SE\\src.zip");
byte[] fileBytes = new byte[100]; //定义文件每次发送大小
//读入到内存中,new 一个inputStream即可
//文件较大,不能一次性发送完毕,因此需要循环操作
fileIn = new FileInputStream(file);
int len = -1;
output = socket.getOutputStream();
while((len = fileIn.read(fileBytes)) != -1) {
output.write(fileBytes, 0, len);
}
System.out.println("发送成功");
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
if(output != null) output.close();
if(fileIn != null) fileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
之后即可多次传输信息不关闭服务端。