基于TCP的网络传输(基于TCP的Socket传输)
传输字符串的小例子:
- 服务端发布一个服务需要绑定端口,每个软件都需要暴露一个端口(MySQL:3306, Oracle:1521),服务器上有很多软件,外界如何定位到具体的软件呢?答案就是:端口号。
- 服务器端绑定端口,绑定之后,客户端就可以访问该服务。
ServerSocket(端口号9999)
- 客户端访问服务,通过如下方式:
Scoket("服务器ip", 端口号9999)
这样服务器和客户端就建立起了双向连接
- 服务器是如何直到客户端发起了连接?答案:服务器端通过ServerSocket的accept()方法进行监听是否有客户端访问。
- 当服务器监听到客户端的访问,也就是连接建立之后,服务器和客户端就可以进行通信了。
(客户服务器通信模型)
代码实现简单的客户端和服务器传送消息:
服务器端代码实现:
public class Server {
@Test
public void serverTest() throws IOException {
// 1. 绑定服务端口号,暴露一个服务,该服务的地址是:本机IP:9999
ServerSocket serverSocket = new ServerSocket(9999);
// 2. 监听是否有客户端访问
// 如果没有客户端访问,则会阻塞,直到有客户端进行访问,才会向下执行
Socket socket = serverSocket.accept();
System.out.println("与客户端成功建立连接");
// 3. 获取输出流,向客户端发送消息
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好啊".getBytes());
System.out.println("------------------------ 下面是服务器接受客户端发送的消息------------------------------");
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
System.out.println("客户端发送的消息是 : " + new String(bytes));
// 4. 关闭连接
inputStream.close();
outputStream.close();
socket.close();
serverSocket.close();
}
}
客户端实现代码:
public class Client {
@Test
public void clientTest() throws IOException {
// 1. 客户端连接服务器Server发布的服务
Socket socket = new Socket("127.0.0.1", 9999);
InputStream inputStream =
socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
System.out.println(new String(bytes));
System.out.println("------------------------ 下面是客户端向服务器发送消息------------------------------");
OutputStream outputStream = socket.getOutputStream();
outputStream.write("server, 你好".getBytes());
outputStream.close();
inputStream.close();
socket.close();
}
}
输出结果:
客户端:
你好啊
------------------------ 下面是客户端向服务器发送消息------------------------------
Process finished with exit code 0
服务器端输出:
与客户端成功建立连接
------------------------ 下面是服务器接受客户端发送的消息------------------------------
客户端发送的消息是 : server, 你好
Process finished with exit code 0
服务器向客户端发送文件的例子:
服务器端代码实现:
public class FileServer {
@Test
public void fileServerTest() throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
Socket socket = serverSocket.accept();
System.out.println("与客户端建立连接!");
// 将文件内容从硬盘读入内存中
FileInputStream fileInputStream = new FileInputStream("data/hello.txt");
OutputStream outputStream = socket.getOutputStream();
// 定义每次发送文件的大小
byte[] buffer = new byte[256];
int len = 0;
// 因为文件内容较大,不能一次发送完毕,因此需要通过循环来分次发送
while ((len = fileInputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
outputStream.close();
fileInputStream.close();
socket.close();
serverSocket.close();
}
}
客户端代码实现:
public class FileClient {
@Test
public void fileClientTest() throws IOException {
Socket socket = new Socket("127.0.0.1", 9999);
FileOutputStream fileOutputStream = new FileOutputStream("data/out.txt");
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[256];
int len = 0;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes, 0, len);
}
inputStream.close();
fileOutputStream.close();
socket.close();
}
}
上述代码,只能实现客户端和服务器端一次文件传输,如果我们想要从客户端向服务器多次发送文件,该怎么实现呢?
服务器端代码实现:
public class ServerReciveFile {
@Test
public void serverReciveFileTest() throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
while (true){
Socket socket = serverSocket.accept();
System.out.println("与客户端建立连接!");
// 将文件内容从硬盘读入内存中
FileInputStream fileInputStream = new FileInputStream("data/hello.txt");
OutputStream outputStream = socket.getOutputStream();
// 定义每次发送文件的大小
byte[] buffer = new byte[256];
int len = 0;
// 因为文件内容较大,不能一次发送完毕,因此需要通过循环来分次发送
while ((len = fileInputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
outputStream.close();
fileInputStream.close();
socket.close();
}
// serverSocket.close(); // 服务器常开,因而不需要进行关闭
}
}
客户端代码实现:
public class ClientSendFile {
@Test
public void clientSendFileTest() throws IOException {
Socket socket = new Socket("127.0.0.1", 9999);
FileOutputStream fileOutputStream = new FileOutputStream("data/out1.txt");
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[256];
int len = 0;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes, 0, len);
}
inputStream.close();
fileOutputStream.close();
socket.close();
}
}
使用多线程实现从客户端向服务器多次发送文件:
服务器端代码实现:
public class MultiThreadServer {
@Test
public void multiThreadServerTest() throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
while (true){
Socket socket = serverSocket.accept();
Thread downloadThread = new Thread(new ClientThread(socket));
downloadThread.start();
}
}
}
class ClientThread implements Runnable{
private Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
FileInputStream fileInputStream = new FileInputStream("data/hello.txt");
byte[] buffer = new byte[256];
int len = 0;
while ((len = fileInputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
outputStream.close();
fileInputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端代码实现:
public class MultiThreadClient {
@Test
public void multiThreadClientTest() throws IOException {
Socket socket = new Socket("127.0.0.1", 9999);
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("data/out3.txt");
byte[] buffer = new byte[256];
int len = 0;
while ((len = inputStream.read(buffer)) != -1){
fileOutputStream.write(buffer, 0, len);
}
fileOutputStream.close();
inputStream.close();
socket.close();
}
}
至此,Java使用Socket远程发送文件介绍结束。