Java TCP transport protocol

Java TCP transport protocol

1 TCP Overview
	TCP相对于UDP比较稳定的传输协议,这里存在三次握手,保证连接状态,同时有明确的客户端和服务端之分
	TCP服务中需要服务器端先启动,需要监听指定端口,等待客户端连接。
	客户端主动连接服务器,和服务器连接之后,才可以进行数据交互,服务器不能主动连接客户端的。

TCP操作而言,Java中提供了两个Socket
	1. 服务端Socket 
		java.net.ServerSocket;
		创建对应的ServerScoket开启服务器,等待客户端连接
	2. 客户端Socket
		java.net.Socket
		创建客户端Scoket,并且连接服务器,同时将Socket发送给服务器绑定注册。

[Picture dump outside the chain fails, the source station may have a security chain mechanism, it is recommended to save the pictures uploaded directly down (img-h3YSYCaP-1583321173104) (img / TCP three-way handshake protocol link .png)]

2 Socket Socket client
给客户端提供数据传输的符合TCP/IP要求的Socket对象

构造方法 Constructor
	Socket(String host, int port);
		host是服务器IP地址,port对应服务器程序的端口号
		通过指定的服务器IP地址和端口号,获取TCP连接对象

成员方法 Method	
	InputStream getInputStream();
		获取Socket对象输入字节流,可以从服务器获取对应的数据
		InputStream是一个资源,需要在程序退出是关闭
		Read
	
	OutputStream getOutputStream();
		获取Sokcet对象输出字节流,可以发送数据到服务器
		OutputStream是一个资源,需要在程序退出是关闭
		Write
	
	void close();
		关闭客户端Socket
	
	void shutdownOutput();
		禁止当前Socket发送数据

TCP/IP协议对应的Socket是给予IO流实现的。
3 ServerSocket server Socket
在服务端开启Socket服务器


构造方法 Constructor:
	ServerSocket(int port);
		开启ServerSocket服务器,并且明确当前服务端口是谁

成员方法 Method:
	Socket accept();
		监听并且连接,得到一个Socket对象,同时该方法是一个阻塞方法,会处于一个始终
		的监听状态
		返回的是Socket,也就是客户端Socket对象,获取到当前Socket对象,相对于获取到
		客户端连接,同时使用的Socket和客户端一致。
4.1 server code
流程:
	1. 创建ServerSocket服务器,同时监听指定端口
	2. 通过accept方法获取Socket连接,得到客户端Socket对象
	3. 通过Socket对象,获取InputStream,读取客户端发送数据
	4. 通过Socket对象,获取OutputStream,发送数据给客户端
	5. 关闭服务
package com.qfedu.c_tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
流程:
	1. 创建ServerSocket服务器,同时监听指定端口
	2. 通过accept方法获取Socket连接,得到客户端Socket对象
	3. 通过Socket对象,获取InputStream,读取客户端发送数据
	4. 通过Socket对象,获取OutputStream,发送数据给客户端
	5. 关闭服务 
 */
public class TcpServer1 {
	public static void main(String[] args) throws IOException {
		System.out.println("服务器启动");
		System.out.println("-----------------------");
		// 1. 创建ServerSocket服务器,同时监听指定端口
		ServerSocket serverSocket = new ServerSocket(8848);
	
		// 2. 通过accept方法获取Socket连接,得到客户端Socket对象
		Socket socket = serverSocket.accept();
		
		// 3. 通过Socket对象,获取InputStream,读取客户端发送数据
		InputStream inputStream = socket.getInputStream();
		
		// IO流操作
		byte[] buf = new byte[1024];
		int length = inputStream.read(buf);
		System.out.println(new String(buf, 0, length));
        
		// 4. 通过Socket对象,获取OutputStream,发送数据给客户端
		OutputStream outputStream = socket.getOutputStream();
		String str = "欢迎来到德莱联盟";
		
		outputStream.write(str.getBytes());
		
		// 5. 关闭Socket服务 同时关闭当前Socket使用的输入字节流和输出字节流	
		// Closing this socket will also close the socket's InputStream and OutputStream. 
		socket.close();	
	}
}
4.2 client code
流程:
	1. 创建Socket服务,同时明确连接服务器的IP地址和对应端口号
	2. 通过Socket对象,获取对应的OutputStream对象,发送数据给服务器
	3. 通过Socket对象,获取对应的InputStream对象,接收服务器发送数据
	4. 关闭服务
package com.qfedu.c_tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/*
流程:
	1. 创建Socket服务,同时明确连接服务器的IP地址和对应端口号
	2. 通过Socket对象,获取对应的OutputStream对象,发送数据给服务器
	3. 通过Socket对象,获取对应的InputStream对象,接收服务器发送数据
	4. 关闭服务
 */
public class TcpClient1 {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("客户端启动");
		System.out.println("------------------------");
		// 1. 创建Socket服务,同时明确连接服务器的IP地址和对应端口号
		Socket socket = new Socket("192.168.31.154", 8848);
		
		// 2. 通过Socket对象,获取对应的OutputStream对象,发送数据给服务器
		OutputStream outputStream = socket.getOutputStream();
		
		outputStream.write("你好服务器!!!".getBytes());
		
		// 3. 通过Socket对象,获取对应的InputStream对象,接收服务器发送数据
		InputStream inputStream = socket.getInputStream();
		
		byte[] buf = new byte[1024];
		int length = inputStream.read(buf);
		System.out.println(new String(buf, 0, length));
		
		// 4. 关闭服务
		socket.close();
	}
}

5 file upload

5.1 client program
流程:
	1. 创建对应文件的输入字节流操作,这里可以使用缓冲
	2. 启动Socket,
	3. 获取Socket输出OutputStream对象,发送数据给服务器
	4. 边读边发
	5. 当文件读取结束,发送完毕,关闭客户端
package com.qfedu.d_fileupload;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/*
流程:
	1. 创建对应文件的输入字节流操作,这里可以使用缓冲
	2. 启动Socket,
	3. 获取Socket输出OutputStream对象,发送数据给服务器
	4. 边读边发
	5. 当文件读取结束,发送完毕,关闭客户端
 */
public class TcpClient {
	public static void main(String[] args) throws IOException {
		// 1. 创建对应文件的输入字节流操作,这里可以使用缓冲
		BufferedInputStream bis = new BufferedInputStream(
				new FileInputStream(new File("D:/aaa/1.mp4")));
		
		// 2. 启动Socket
		Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(), 8848);
		
		// 3. 获取Socket输出OutputStream对象,发送数据给服务器
		OutputStream outputStream = socket.getOutputStream();
		
		int length = -1;
		byte[] buf = new byte[1024 * 8];
		
		
		// 4. 读取数据,发送数据
		while ((length = bis.read(buf)) != -1) {
			outputStream.write(buf, 0, length);
		}
		
		// 5. 关闭资源
		socket.close();
		bis.close();
	}
}
5.2 server program
流程:
	1. 开启服务端服务,创建ServerSocket对象
	2. 明确保存文件的位置,创建对应文件夹的输出缓冲字节流
	3. 读取数据,写入文件
	4. 关闭服务器
package com.qfedu.d_fileupload;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
流程:
	1. 开启服务端服务,创建ServerSocket对象
	2. 明确保存文件的位置,创建对应文件夹的输出缓冲字节流
	3. 读取数据,写入文件
	4. 关闭服务器
 */
public class TcpServer {
	public static void main(String[] args) throws IOException {
		// 1. 开启服务端服务,创建ServerSocket对象
		ServerSocket serverSocket = new ServerSocket(8848);
		
		Socket socket = serverSocket.accept();
		
		// 2. 明确保存文件的位置,创建对应文件夹的输出缓冲字节流
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(
						new File("D:/aaa/temp.mp4")));
		
		// 3. 获取Socket对应的输入流
		InputStream inputStream = socket.getInputStream();
		
		// 4. 边读边写
		int length = -1;
		byte[] buf = new byte[1024 * 8];
		
		while ((length = inputStream.read(buf)) != -1) {
			bos.write(buf, 0, length);
		}
		
		// 5. 关闭资源
		bos.close();
		socket.close();
	}
}
Currently 5.3 server-side code issues
1. 保存的文件名都是一致的,无法保存多个文件。
	这里可以考虑使用UUID作为文件名
2. 服务端代码肯定不能执行完一个上传功能就结束

3. 服务端代码不可能只有一个上传文件功能
	多线程
Published 12 original articles · won praise 19 · views 9719

Guess you like

Origin blog.csdn.net/LioTomcat/article/details/104660395