Java 网络编程案例二:多态客户端与服务器之间的多次通信

  通常情况下,服务器不应该只接受一个客户端请求,而应该不断地接受来自客户端的所有请求,所以Java程序通常会通过循环,不断地调用ServerSocket的accept()方法。

  如果服务器端要“同时”处理多个客户端的请求,因此服务器端需要为每一个客户端单独分配一个线程来处理,否则无法实现“同时”。

  需求:多个客户端连接服务器,并进行多次通信

    •  每一个客户端连接成功后,从键盘输入单词或词组,并发送非服务器;
    •     服务器收到客户端的消息后,把词语“反转”后返回给客户端;
    •     客户端接收服务器返回的“词语”,打印显示;
    •     当客户端输入“stop”时断开与服务器的连接;
    •     多个客户端可以同时给服务器发送“词语”,服务器可以“同时”处理多个客户端的请求;
    •     服务器端要“同时”处理多个客户端的请求,那么必须使用多线程,每一个客户端的通信需要单独的线程来处理。

  客户端程序示例代码:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {

    public static void main(String[] args) throws Exception {
        // 1、准备Socket,连接服务器,需要指定服务器的IP地址和端口号
        Socket socket = new Socket("127.0.0.1", 8888);

        // 2、获取输出流,用来发送数据给服务器
        OutputStream out = socket.getOutputStream();
        PrintStream ps = new PrintStream(out);
        
        // 3、获取输入流,用来接收服务器发送给该客户端的数据
        InputStream input = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(input));
        
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.println("输入发送给服务器的单词或成语:");
            String message = scanner.nextLine();
            if(message.equals("stop")){
                socket.shutdownOutput();
                break;
            }
            
            // 4、 发送数据
            ps.println(message);
            // 接收数据
            String feedback  = br.readLine();
            System.out.println("从服务器收到的反馈是:" + feedback);
        }
        
        //5、关闭socket,断开与服务器的连接
        scanner.close();
        socket.close();
    }
}

  服务器端程序示例代码:

import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args)throws Exception {
        // 1、准备一个ServerSocket
        ServerSocket server = new ServerSocket(8888);
        System.out.println("等待连接...");
        
        int count = 0;
        while(true){
            // 2、监听一个客户端的连接
            Socket socket = server.accept();
            System.out.println("第" + ++count + "个客户端连接成功!!");
            
            ClientHandlerThread ct = new ClientHandlerThread(socket);
            ct.start();
        }
        
        //这里没有关闭server,永远监听
    }
}

  服务器端处理客户端请求的线程类示例代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

public class ClientHandlerThread extends Thread{
    private Socket socket;

    public ClientHandlerThread(Socket socket) {
        super();
        this.socket = socket;
    }
    
    public void run(){
        
        try{
            //(1)获取输入流,用来接收该客户端发送给服务器的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //(2)获取输出流,用来发送数据给该客户端
            PrintStream ps = new PrintStream(socket.getOutputStream());
            String str;
            // (3)接收数据
            while ((str = br.readLine()) != null) {
                //(4)反转
                StringBuilder word = new StringBuilder(str);
                word.reverse();
                
                //(5)返回给客户端
                ps.println(word);
            }
        }catch(Exception  e){
            e.printStackTrace();
        }finally{
            try {
                //(6)断开连接
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

相关推荐