Java 网络编程

软件结构 & 网络通信协议

C/S结构: Client/Server 结构, 是指客户端和服务器结构, 常见的程序有 QQ, 迅雷等软件

B/S结构: Browser/Server结构, 是指浏览器和服务器结构, 常见的程序有 Google, Firefox 等

两种结构各有优势, 都离不开网络的支持, 网络编程, 就是在一定协议下, 实现两台计算机的通信的程序.

TCP协议

面向连接的通信, 客户端和服务端必须经过3次握手, 建立逻辑连接, 才能通信

通信的步骤:

  1. 服务端启动

  2. 客户端请求服务端, 建立逻辑连接 (IO对象 socket)

  3. 客户端和服务端之间通过 socket 进行通信

多个客户端同时和服务端交互, 在服务端有一个 accept() 方法, 获取到请求的客户端对象

服务端是没有 IO 对象的, 它可以获取到客户端的 socket, 来和每个客户端通信

ServerSocket & Socket 类

Serversocket

java.net.ServerSocket: 实现了服务端套接字, 等待客户端套接字请求

构造方法:

public ServerSocket(int port): 创建绑定到指定端口号的服务器套接字

成员方法:

  1. public Socket accept(): 侦听并返回客户端的套接字, 然后使用客户端的套接字与客户端进行交互

  2. public void close(): 关闭套接字, 释放资源

Socket

java.net.Socket: 实现了客户端的套接字, 套接字是两台机器之间通信的端点

套接字是包含了 IP 地址和端口号的网络单位

构造方法:

Socket(String host, int port): 创建一个流套接字, 并将其连接到指定主机, 指定端口

成员方法:

  1. OutputStream getOutputStream(): 返回套接字的输出流

  2. InputStream getInputStream(): 返回套接字的输入流

  3. void close(): 关闭此套接字

demo:

server

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

public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 创建 server socket
        ServerSocket server  = new ServerSocket(9000);
        // 获取客户端连接
        Socket socket = server.accept();
        // 获取输入 IO流对象
        InputStream is = socket.getInputStream();
        // 读取 数据
        byte[] bytes = new byte[1024];
        int dataLen = is.read(bytes);
        System.out.println("来自客户端的消息: " + new String(bytes, 0, dataLen));
        // 发送数据
        OutputStream os = socket.getOutputStream();
        os.write("收到了".getBytes("UTF-8"));
        os.flush();

        //释放资源
        socket.close();
        server.close();
    }
}

client

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


public class TCPClient {
    public static void main(String[] args) throws IOException {
        // 创建 socket, 这里就连接服务器的地址和端口了
        Socket socket  = new Socket("localhost", 9000);
        // 获取输出 IO流 对象
        OutputStream os = socket.getOutputStream();
        // 写入 IO 流,  发送到服务端
        os.write("hello world".getBytes("UTF-8"));
        os.flush();
        System.out.println("信息发送成功");

        //接收服务端的信息
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int dataLen = is.read(bytes);
        System.out.println("来自服务端的响应: " + new String(bytes, 0, dataLen));

        //释放资源
        socket.close();
    }
}

文件传输案例

把桌面上的文件由客户端传给服务端, 然后服务端改个名字保存到桌面

server

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 创建 server socket
        ServerSocket server  = new ServerSocket(9000);
        // 获取客户端连接
        Socket socket = server.accept();
        // 获取输入 IO流对象
        InputStream is = socket.getInputStream();
        // 创建文件 IO输出流, 写到本地
        File f = new File("C:\Users\chenkai\Desktop");
        FileOutputStream fos = new FileOutputStream(f.getAbsoluteFile() + "\test2.jpg");
        // 读取 socket 数据, 写到文件输入流
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = is.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }

        // 文件写入完成, 告诉客户端
        OutputStream os = socket.getOutputStream();
        os.write("文件上传完成".getBytes("UTF-8"));
        System.out.println("文件写入完成");

        //释放资源
        fos.close();
        socket.close();
        server.close();
    }
}

client

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


public class TCPClient {
    public static void main(String[] args) throws IOException, IOException {
        // 创建 socket, 这里就连接服务器的地址和端口了
        Socket socket  = new Socket("localhost", 9000);
        // 获取输出 IO流 对象
        OutputStream os = socket.getOutputStream();
        // 获取文件输入流
        FileInputStream fis = new FileInputStream("C:\Users\chenkai\Desktop\test.jpg");
        //
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1) {
            // 写入 IO 流,  发送到服务端
            os.write(bytes);
        }
        // 告诉服务端, 文件写入完成
        socket.shutdownOutput();
        System.out.println("文件上传完成");

        //接收服务端的信息
        InputStream is = socket.getInputStream();
        while ((len = is.read(bytes)) != -1) {
            System.out.println("来自服务端的响应: " + new String(bytes,0,len, "UTF-8"));
        }

        //释放资源
        fis.close();
        socket.close();
    }
}

模拟BS结构服务器分析

浏览器向TCP服务器发送请求, 服务器返回一张图片给浏览器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class HTTPServer {
    public static void main(String[] args) throws IOException {
        // 创建 server socket
        ServerSocket server  = new ServerSocket(9000);
        while(true) {
            // 获取客户端连接
            Socket socket = server.accept();
            // 获取输入 IO流对象
            InputStream is = socket.getInputStream();
            // 读取 socket 数据
    //        int len = 0;
    //        byte[] bytes = new byte[1024];
    //        while ((len = is.read(bytes))!=-1){
    //            System.out.println(new String(bytes, 0, len));
    //        }
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String firstLine = br.readLine();
            String fileName = firstLine.split(" ")[1].substring(1);
            System.out.println("C:\" + fileName.replace("/", "\"));
            fileName = "C:\" + fileName.replace("/", "\");
            // 读取本地文件
//            FileInputStream fis = new FileInputStream("C:\Users\chenkai\Desktop\test.jpg");
            FileInputStream fis = new FileInputStream(fileName);
            // 将一张图片回写给浏览器
            OutputStream os = socket.getOutputStream();
            os.write("HTTP/1.1 200 OK
".getBytes("UTF-8"));
            os.write("Content-Type: image/jpg
".getBytes("UTF-8"));
            os.write("
".getBytes("UTF-8"));
            //
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = fis.read(bytes)) != -1) {
                os.write(bytes, 0, len);
            }

            //释放资源
            br.close();
            fis.close();
            socket.close();
        }
        //server.close();
    }
}

ending ~ 

每天都要遇到更好的自己.
原文地址:https://www.cnblogs.com/kaichenkai/p/11821995.html