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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31615049/article/details/87437719

一、编写服务端代码

在本示例中,服务端主要作用是监听客户端的连接,获取客户端发送的数据。

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

package com.io.socket.server;

import java.net.ServerSocket;

/**
 * @program: com.io.socket.server
 * @description: Socket服务端启动类
 * @author: liujinghui
 * @create: 2019-02-16 10:39
 **/
public class SocketServer {

    public static void main(String[] args) throws Exception{
        SocketServerListenHandler socketServerListenHandler = new SocketServerListenHandler(6666);
        socketServerListenHandler.listenClientConnect();
    }
}

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

package com.io.socket.server;

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

/**
 * @program: com.io.socket.server
 * @description: 服务端监听类
 * 监听客户端的请求
 * @author: liujinghui
 * @create: 2019-02-16 10:39
 **/
public class SocketServerListenHandler {

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

    /**
     * 构造方法
     * @param port 端口
     */
    public SocketServerListenHandler(int port){
        try{
            serverSocket = new ServerSocket(port);
            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(){
        while(true){
            try {
                System.out.println("服务端监听开始。。。");
                Socket clientConnectSocket = serverSocket.accept();
                System.out.println("监听到客户端连接。。。创建处理客户端连接的handler工具。。");
                new SocketServerClientHandler(clientConnectSocket).start();
            } catch (Exception e) {
                System.out.println("服务端监听连接程序异常");
            }
        }
    }
}

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

  • 服务端客户连接处理:服务端主线程不断地轮询客户端的连接,一个客户发起了连接,那么服务端就有义务为每一个客户端创建一个服务端客户消息处理线程。
  • 服务端客户消息处理:针对一个Socket,不断轮询传输过来的byte流,比如客户可能5秒钟发一次消息,那么服务端客户消息处理线程就应该接收到5秒一次的消息。
package com.io.socket.server;

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

/**
 * @program: com.io.socket.server
 * @description: 服务端客户消息处理线程类
 * @author: liujinghui
 * @create: 2019-02-16 11:02
 **/
public class SocketServerClientHandler extends Thread{

    //每个消息通过Socket进行传输
    private Socket clientConnectSocket;
    public SocketServerClientHandler(Socket clientConnectSocket){
        this.clientConnectSocket = clientConnectSocket;
    }

    @Override
    public void run(){
        try {
            InputStream inputStream = clientConnectSocket.getInputStream();
            while (true) {
                byte[] data = new byte[100];
                int len;
                while ((len = inputStream.read(data)) != -1) {
                    String message = new String(data, 0, len);
                    System.out.println("客户端传来消息: " + message);
                    clientConnectSocket.getOutputStream().write(data);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
     }
}

二、编写客户端代码

 第一步:客户端的逻辑很简单,创建三个客户,传入host,端口,客户端的名称,发送间隔时间,发送内容消息。

package com.io.socket.client;

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

/**
 * @program: com.io.socket.client
 * @description: 客户端测试启动类
 * @author: liujinghui
 * @create: 2019-02-16 10:39
 **/
public class SocketClient {

    public static void main(String[] args) throws IOException {
        //服务端IP和端口 创建客户端服务端socket
        new Thread(new SocketClientWorker("127.0.0.1", 6666,"ClientA",5000,"A发送消息。。")).start();
        new Thread(new SocketClientWorker("127.0.0.1", 6666,"ClientB",4000,"B发送消息。。")).start();
        new Thread(new SocketClientWorker("127.0.0.1", 6666,"ClientC",3000,"C发送消息。。")).start();
    }
}

第二步:客户端socket线程实例,通过Socket的getOutputStream().write(message.getBytes())方法传入message信息

package com.io.socket.client;

import java.net.Socket;

/**
 * @program: com.io.socket.client
 * @description: 客户端工作线程
 * @author: liujinghui
 * @create: 2019-02-16 12:06
 **/
public class SocketClientWorker implements Runnable{

    //通信socket
    private Socket clientSocket;
    //客户端名称
    private String clientName;
    //发送消息间隔
    private long sleepTime;
    //发送的消息内容
    private String message;

    public SocketClientWorker(String host,int port,String clientName,long sleepTime,String message){
        try{
            clientSocket= new Socket(host, port);
            this.clientSocket = clientSocket;
            this.clientName = clientName;
            this.sleepTime = sleepTime;
            this.message =  message;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        {
            while (true) {
                try {
                    clientSocket.getOutputStream().write(message.getBytes());
                    System.out.println(clientName + "客户端向服务器发送消息: " + message);
                    Thread.sleep(sleepTime);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

三、测试

展开阅读全文

没有更多推荐了,返回首页