一、导读
本文主要内容包括如何使用 Java 编写 TCP 网络通信程序,然后实现一个文件上传
二、TCP通信简介
服务端程序监听在服务器的某一个端口上,等待客户端的连接,负责监听的是监听套接字(Listen_socket
),当有客户端连接时,操作系统会创建一个新的套接字 connect_socket
,这个套接字专门负责与刚刚连接的客户端进行通信,listen_socket
则继续监听。
客户端要想与服务端进行通信,首先需要创建一个 Socket
,然后指定服务器的 IP 地址和端口号进行连接。
三、TCP通信具体实现
服务端:
/**
* 服务端
*
* @author JiaMing
* @since 2021/12/16/0016 上午 11:47
**/
public class ServerTest {
public static void main(String[] args) throws IOException {
//new一个ServerSocket对象,指定端口号为1027
ServerSocket serverSocket = new ServerSocket(1027);
System.out.println("等待连接");
//使用ServerSocket对象中的accept方法,获取到请求的客户端Socket
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//读取客户端发来的信息
//使用 Socket对象中的getInputStream方法,获取到网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
//使用InputStream对象中的read方法读取客户端发送的数据
int len = is.read(bytes);
System.out.println(new String(bytes, 0, len));
//向客户端回应
//使用Socket对象中的getOutputStream方法,获取到网络字节输出流OutputStream对象
OutputStream os = socket.getOutputStream();
//使用OutputStream对象中的write方法,给客户端发送数据
os.write("收到!————————————>来自服务器".getBytes(StandardCharsets.UTF_8));
//关闭socket
socket.close();
//关闭服务器
serverSocket.close();
}
}
客户端:
/**
* 客户端
*
* @author JiaMing
* @since 2021/12/16/0016 上午 11:46
**/
public class ClientTest {
public static void main(String[] args) throws IOException {
//创建一个客户端Socket对象,构造方法中绑定服务器的 IP 地址和端口号
Socket socket = new Socket("127.0.0.1", 1027);
//向服务端发送信息
OutputStream os = socket.getOutputStream();
//使用OutputStream对象中的write方法,给服务器发送数据
os.write("你好,我是佳明————————————>来自客户端".getBytes(StandardCharsets.UTF_8));
//读消息
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
//使用InputStream对象中的read方法读取服务器反馈的数据
int length = is.read(bytes);
System.out.println(new String(bytes, 0, length));
//关闭socket
socket.close();
}
}
依次打开服务端,客户端
四、文件上传具体实现
服务端:
/**
* 服务端
*
* @author JiaMing
* @since 2021/12/16/0016 下午 14:42
**/
public class Server {
public static void saveFile(Socket socket) throws IOException {
try {
//使用Socket对象中的getInputStream方法,获取到网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//判断这个目录是否存在,不存在则创建
File file = new File("D:\\temp\\upload");
if (!file.exists()) {
file.mkdirs();
}
String fileName = ".txt";
//创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
FileOutputStream fos = new FileOutputStream(file+fileName);
int len;
byte[] bytes = new byte[1024];
System.out.println("服务端开始向硬盘写入文件");
while ((len = is.read(bytes)) != -1) {
//把读取到的文件保存到服务器的硬盘上
fos.write(bytes, 0, len);
}
System.out.println("服务端读取文件完毕!");
//反馈给客户端
socket.getOutputStream().write("文件上传成功".getBytes(StandardCharsets.UTF_8));
//释放资源
fos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
//创建一个服务器ServerSocket对象,指定端口号1027
ServerSocket server = new ServerSocket(1027);
while (true) {
System.out.println("等待连接");
//使用ServerSocket对象中的方法accept,获取到请求的客户端Socket
Socket socket = server.accept();
System.out.println("连接成功");
//当有客户端连接时,创建一个新的线程处理客户端请求
new Thread(() -> {
try {
saveFile(socket);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
客户端:
/**
* 客户端
*
* @author JiaMing
* @since 2021/12/16/0016 下午 14:43
**/
public class Client {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\carInfo.txt");
//创建一个客户端Socket对象
Socket socket = new Socket("127.0.0.1", 1027);
//读取本地文件
OutputStream os = socket.getOutputStream();
int len;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
//把读取到的文件上传到服务器
os.write(bytes, 0, len);
}
//关闭此套接字的输出流
socket.shutdownOutput();
//使用Socket中的getInputStream,获取网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
System.out.println("文件发送完毕!");
//使用网络字节输入流InputStream对象中的方法read读取服务器回写的数据
while ((len = is.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//释放资源
fis.close();
socket.close();
}
}
运行结果:
OK,完成!
参考文章:https://zhuanlan.zhihu.com/p/112731150