java编写简单的Socket通信应用 实现服务端同时处理多个客户端

第一步:编写服务端主启动类,代码很简单,new一个自定义SocketServerListenHandler类,构造器传入端口号,并启动监听方法listenClientConnect()执行监听客户端连接。注:它的职责仅仅是监听连接。

 1 import java.net.ServerSocket;
 2 
 3 /**
 4  * @author CKFuture
 5  * @since 2021-01-05
 6  * @description Socket服务端启动类
 7  **/
 8 public class SocketServer {
 9 
10     private static final int PORT = 8400;//监听的端口号
11     private static final String HostName="127.0.0.1";//服务器IP
12 
13     public static void main(String[] args) throws Exception{
14         SocketServerListenHandler socketServerListenHandler = new SocketServerListenHandler(HostName,PORT);
15         socketServerListenHandler.listenClientConnect();
16     }
17 }

第二步:编写自定义SocketServerListenHandler类,从类名可以获知,该类是一个存在于Server端的Socket监听处理类,它的职责就是轮训我们所需端口(本例中是8400),一旦发现有客户端连接,就立即创建创建一个工作线程去处理客户端发送的消息。

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

/**
 * @author CKFuture
 * @since 2021-01-05
 * @description 服务端监听类
 * 监听客户端的请求
 **/
public class SocketServerListenHandler {

    //A server socket waits for requests to come in over the network.
    //这是一个不断等待获取网络传入请求的服务端Socket
    private ServerSocket serverSocket;

    /**
     * 构造方法
     * @param port 端口
     */
    public SocketServerListenHandler(String hostname,int port){
        try{
            //serverSocket = new ServerSocket(port);
            serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(hostname, port));
            System.out.println("SocketServer服务端:"+serverSocket.getInetAddress()+":"+serverSocket.getLocalPort()+"");

            this.serverSocket = serverSocket;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 无限循环的监听客户端的连接
     * Listens for a connection to be made to this socket and accepts it.
     * 当有一个连接产生,将结束accept()方法的阻塞
     * The method blocks until a connection is made.
     */
    public void listenClientConnect(){
        int i=0;
        while(true){
            try {
                System.out.println(i+"号服务端监听开始。。。");
                Socket clientConnectSocket = serverSocket.accept();

                //客户端地址信息:IP和端口号
                SocketAddress clientAddress =clientConnectSocket.getRemoteSocketAddress();
                System.out.println("监听到客户端连接。。。"+clientAddress);

                new SocketServerClientHandler(clientConnectSocket).start();
            } catch (Exception e) {
                System.out.println("服务端监听连接程序异常");
            }
            i++;
        }
    }
}

第三步:处理客户端请求数据。我们知道一台服务器通常要面对成千上万的客户连接,如果我们采用串行的方式,收到一个请求就调用主线程去处理,结果其他的客户端就要被迫等待。所以针对这种情况我们的服务端客户消息处理应该采用并行方式,即new出每一个客户消息工作线程,在不同的线程中处理客户请求的数据。这里请大家区分客户连接处理和客户消息处理。

  • 服务端客户连接处理:服务端主线程不断地轮询客户端的连接,一个客户发起了连接,那么服务端就有义务为每一个客户端创建一个服务端客户消息处理线程。
  • 服务端客户消息处理:针对一个Socket,不断轮询传输过来的byte流,比如客户可能5秒钟发一次消息,那么服务端客户消息处理线程就应该接收到5秒一次的消息。
 1 import java.io.InputStream;
 2 import java.net.Socket;
 3 import java.net.SocketAddress;
 4 
 5 /**
 6  * @author CKFuture
 7  * @since 2021-01-05
 8  * @description 服务端客户消息处理线程类
 9  **/
10 public class SocketServerClientHandler extends Thread{
11 
12     //每个消息通过Socket进行传输
13     private Socket clientConnectSocket;
14     //客户端地址
15     private SocketAddress clientAddress;
16 
17     public SocketServerClientHandler(Socket clientConnectSocket){
18         this.clientConnectSocket = clientConnectSocket;
19         clientAddress =clientConnectSocket.getRemoteSocketAddress();
20     }
21     @Override
22     public void run(){
23         try {
24             InputStream inputStream = clientConnectSocket.getInputStream();
25             while (true) {
26                 byte[] data = new byte[100];
27                 int len;
28                 while ((len = inputStream.read(data)) != -1) {
29                     String message = new String(data, 0, len);
30                     System.out.println(clientAddress+": " + message);
31                     clientConnectSocket.getOutputStream().write(data);
32                 }
33             }
34         } catch (Exception e) {
35             e.printStackTrace();
36         }
37     }
38 }

测试结果:

 

posted @ 2021-01-05 15:48  创客未来  阅读(661)  评论(0编辑  收藏  举报