• 【东软实训Day2】用Java实现客户端与服务器交互


    一、客户端-服务器编程模型

    1个应用 = 1个服务器进程 + 1…N个客户端进程,其中服务器管理资源,并通过操作这种资源为客户端服务。

    客户端-服务器模型中的基本操作是事务(transaction)(注:不同于数据库中的transaction)。
    一个客户端-服务器事务
    Step1:客户端向服务器发送一个请求,发起一个事务;

    Step2:服务器收到请求后,进行解释,并以适当的方式操作它的资源;

    Step3:服务器给客户端发送一个响应,并等待下一个请求;

    Step4:客户端收到响应并处理。

    二、Java客户端和服务端建立连接的过程

    Java客户端和服务端建立连接的过程可以分为以下几个步骤:

    1.创建Socket对象

    要实现一个需随时待命的服务器应用,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket用来等待客户端的请求。一旦获得一个连接请求,就创建一个Socket对象来与服务器进行通信。

    ServerSocket ss = new ServerSocket(port);
    Socket s = ss.accept();
    
    • 1
    • 2

    2. 创建套接字

    在Java中,Socket是用于建立网络连接的基本类。服务器客户端需要创建一个Socket对象,一个Socket类代表一个客户端套接字,以便与服务端建立连接。

    Socket socket = new Socket("服务器IP地址", 服务器端口);
    
    • 1

    3. 获取输入输出流

    客户端需要获取Socket对象的输入输出流,以便向服务端发送请求和接收服务端的响应。

    OutputStream os = socket.getOutputStream();
    InputStream is = socket.getInputStream();
    
    • 1
    • 2

    4. 发送请求

    客户端向服务端发送请求,可以通过输出流将请求数据发送给服务端。

    os.write("请求数据".getBytes());
    
    • 1

    5. 接收响应

    服务端接收到客户端的请求后,会返回相应的数据。客户端可以通过输入流接收服务端的响应。

    byte[] buffer = new byte[1024];
    int len;
    while ((len = is.read(buffer)) != -1) {
    	System.out.println(new String(buffer, 0, len));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6. 关闭连接

    客户端在完成请求和响应后,需要关闭与服务端的连接。

    socket.close();
    
    • 1

    三、服务器Server与客户端Client的代码示例:

    1. Server代码

    public class Server {
        public static void main(String[] args) {
            // 创建服务器
            // 创建ServerSocket对象
            try {
                // 启动服务器
                System.out.println("原神,启动!");
                ServerSocket ss = new ServerSocket(8888);
                // 等待客户,如果有可断来访问,就创建一个
                // 针对该客户端的一个Socket对象
                Socket s = ss.accept();
    
                // 每个socket都是一个io对象
                // 输入读取客户端发送过来的请求
                InputStream is = s.getInputStream();
                byte[]bytes = new byte[1024];
                int len = 0;
                len = is.read(bytes);
                String req = new String(bytes, 0, len, "utf-8");
                System.out.println(req);
    
                // 响应服务器
                OutputStream os = s.getOutputStream();
                String resp = "请求已收到,这是返回响应";
                os.write(resp.getBytes("utf-8"));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2. Client代码

    public class Client {
        public static void main(String[] args) throws IOException {
            // 创建套接字对象访问服务器端口
            Socket s = new Socket("127.0.0.1", 8888);
    
            OutputStream os = s.getOutputStream();
            os.write("这里是客户端,收到请回答".getBytes("utf-8"));
    
            InputStream is = s.getInputStream();
            int len = 0;
            byte[]bytes = new byte[1024];
            len = is.read(bytes);
            System.out.println(new String(bytes, 0, len, "utf-8"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    四、结合实际

    现阶段的服务器大多都不会是1对1,而是为多个客户端提供服务,面向更多的用户,则需要使用多线程以及网络编程。代码示例如下:

    ServerSocket ss = new ServerSocket(8888);
    // 等待创建套接字
    while (true) {
    	Socket s = ss.accept();
    	new ServerThread(s).start();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    编写线程类,传递Socket对象,要实现的功能,就通过run方法调用,或者直接写在run方法中。

    @Override
    public void run() {
    	try {
    		// 文件的保存位置
    		String uuid = UUID.randomUUID().toString();
    		FileOutputStream fos = new FileOutputStream("img/" + uuid);
    		// 读取客户端发送的文件
    		byte[]bytes = new byte[1024];
    		int len = 0;
    		len = s.getInputStream().read(bytes);
    		fos.write(bytes, 0, len);
    		fos.close();
    		File file = new File("img/" + uuid);
    		file.renameTo(new File("img/" + uuid + ".png"));
    	} catch (FileNotFoundException e) {
    		throw new RuntimeException(e);
    	} catch (IOException e) {
    		throw new RuntimeException(e);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    五、注意事项

    在Java客户端和服务端建立连接的过程中,需要注意以下几点:

    1. IP地址和端口号

    客户端需要知道服务端的IP地址和端口号,才能与服务端建立连接。IP地址是服务端的唯一标识符,端口号是服务端程序的监听端口。

    2. 输入输出流的关闭

    在使用输入输出流时,需要注意及时关闭流,否则会导致资源泄露。

    3. 异常处理

    在建立连接的过程中,可能会出现各种异常。客户端需要对异常进行适当处理,以保证程序的稳定性。

  • 相关阅读:
    2016 NIPS | Variational Graph Auto-Encoders
    python 表白代码 biu 比心
    星空下的对话,有感
    猿创征文|在工作中彻底搞懂原型和原型链的原理
    远程仓库.github/workflow的 yml如何配置
    [附源码]java毕业设计旅游管理系统
    kafka的原理及集群部署详解
    一文学懂java泛型
    Dcoker配置Rabbitmq集群
    vue面试题
  • 原文地址:https://blog.csdn.net/u014571143/article/details/132760072