一、TCP通信分析图解
- 【服务端】启动,创建 ServerSocket 对象,等待连接。
- 【客户端】启动,创建 Socket 对象,请求连接。
- 【服务端】接收连接,调用 accept 方法,并返回一个 Socket 对象。
- 【客户端】Socket 对象,获取 OutputStream,向服务端写出数据。
- 【服务端】Scoket 对象,获取 InputStream,读取客户端发送的数据。
到此,客户端向服务端发送数据成功。

自此,服务端向客户端回写数据。
- 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
- 【客户端】Scoket对象,获取InputStream,解析回写数据。
-
二、客户端向服务端发送数据
服务端实现
public class TCPServer {public static void main(String[] args) throws IOException {//1.创建服务器ServerSocket对象和系统要指定的端口号ServerSocket server = new ServerSocket(8888);//2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象SocketSocket socket = server.accept();//3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象InputStream is = socket.getInputStream();//4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes,0,len));//5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象OutputStream os = socket.getOutputStream();//6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据os.write("收到谢谢".getBytes());//7.释放资源(Socket,ServerSocket)socket.close();server.close();}}
客户端实现
public static void main(String[] args) throws IOException {//1.创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号Socket socket = new Socket("127.0.0.1",8888);//2.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象OutputStream os = socket.getOutputStream();//3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据os.write("你好服务器".getBytes());//4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象InputStream is = socket.getInputStream();//5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes,0,len));//6.释放资源(Socket)socket.close();}
三、经典案例
1、文件上传
客户端
public class FileUpload_Client {public static void main(String[] args) throws IOException {// 1.创建流对象// 1.1 创建输入流,读取本地文件BufferedInputStream bis = new BufferedInputStream(new FileInputStream("15-Socket/test.jpg"));// 1.2 创建输出流,写到服务端Socket socket = new Socket("localhost", 6666);BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());//2.写出数据.byte[] b = new byte[1024 * 8];int len;while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);bos.flush();}System.out.println("文件发送完毕");// 3.释放资源bos.close();socket.close();bis.close();System.out.println("文件上传完毕 ");}}
服务端
public class FileUpload_Server {public static void main(String[] args) throws IOException {System.out.println("服务器 启动..... ");// 1. 创建服务端ServerSocketServerSocket serverSocket = new ServerSocket(6666);// 2. 循环接收,建立连接while (true) {/*3. socket对象交给子线程处理,进行读写操作Runnable接口中,只有一个run方法,使用lambda表达式简化格式*/Socket accept = serverSocket.accept();new Thread(() -> {try (//3.1 获取输入流对象BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());//3.2 创建输出流对象, 保存到本地 .FileOutputStream fos = new FileOutputStream("15-Socket/" + System.currentTimeMillis() + ".jpg");BufferedOutputStream bos = new BufferedOutputStream(fos);) {// 3.3 读写数据byte[] b = new byte[1024 * 8];int len;while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);}// 4.=======信息回写===========================System.out.println("back ........");OutputStream out = accept.getOutputStream();out.write("上传成功".getBytes());out.close();//================================//5. 关闭 资源bos.close();bis.close();accept.close();System.out.println("文件上传已保存");} catch (IOException e) {e.printStackTrace();}}).start();}}}
2、模拟web服务器
原理:浏览器将地址栏的地址传输到web服务器,web服务器根据地址去检索服务器上的文件,并将内容输出到浏览器。
public class ServerDemo {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);while (true) {Socket socket = server.accept();new Thread(new Web(socket)).start();}}static class Web implements Runnable {private Socket socket;public Web(Socket socket) {this.socket = socket;}public void run() {try {//转换流,读取浏览器请求第一行BufferedReader readWb = newBufferedReader(new InputStreamReader(socket.getInputStream()));String requst = readWb.readLine();//取出请求资源的路径String[] strArr = requst.split(" ");System.out.println(Arrays.toString(strArr));// 去掉web前面的/String path = strArr[1].substring(1);System.out.println(path);// 读取客户端请求的资源文件FileInputStream fis = new FileInputStream(path);System.out.println(fis);byte[] bytes = new byte[1024];int len = 0;//向浏览器 回写数据OutputStream out = socket.getOutputStream();// 写入HTTP协议响应头,固定写法out.write("HTTP/1.1 200 OK\r\n".getBytes());out.write("Content-Type:text/html\r\n".getBytes());// 必须要写入空行,否则浏览器不解析out.write("\r\n".getBytes());while ((len = fis.read(bytes)) != -1) {out.write(bytes, 0, len);}fis.close();out.close();readWb.close();socket.close();} catch (Exception ex) {}}}}
四、其他
