欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 网络通信 — 使用线程池搭建TCP BIO通信服务器

程序员文章站 2022-06-06 08:02:18
...

服务端使用一个线程池大小为5个线程去监听socket


package top.yuyufeng.test;

import org.junit.Test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 服务端
 * created by yuyufeng on 2017/8/18.
 */
public class TestTcpServer {
    private static ExecutorService executor = Executors.newFixedThreadPool(5);
    private static AtomicInteger count = new AtomicInteger();

    // 服务端
    public static void main(String[] args) throws ClassNotFoundException {
        ServerSocket ss = null;
        Socket s = null;
        try {
            ss = new ServerSocket(8989);
            System.out.println("服务端已经启动...");
            while (true) {
                int id = count.getAndAdd(1);
                executor.execute(new ServerTask(id, ss.accept()));
                System.out.println("执行一次响应.." + id);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ss != null) {
                try {
                    ss.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }
}

class ServerTask implements Runnable {
    private Integer id;//任务标记
    private Socket socket;

    public ServerTask(Integer id, Socket socket) {
        this.id = id;
        this.socket = socket;
    }

    public void run() {
        ObjectOutputStream os = null;
        ObjectInputStream is = null;
        try {
            is = new ObjectInputStream(socket.getInputStream());
            //读取第一部分数据
            TransportObject transportObject = (TransportObject) is.readObject();
            System.out.println(transportObject.toString() + "任务标记:" + id);
            //读取第二部分数据
            transportObject = (TransportObject) is.readObject();
            System.out.println(transportObject.toString() + "任务标记:" + id);
            os = new ObjectOutputStream(socket.getOutputStream());
            os.writeObject(new TransportObject(1, "我是客户端!"));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}


客户端启动6个线程去请求服务器

package top.yuyufeng.test;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Random;

/**
 * 客户端
 * created by yuyufeng on 2017/8/18.
 */
public class TestTcpClient {

    public static void main(String[] args) throws ClassNotFoundException, InterruptedException {
//        send();
        for (int i = 0; i < 6; i++) {
            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            send();
                            Thread.sleep(100);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }


    }

    private static void send() throws ClassNotFoundException {
        Socket socket = null;
        ObjectOutputStream os = null;
        ObjectInputStream is = null;
        try {
            socket = new Socket(InetAddress.getByName("127.0.0.1"), 8989);
            os = new ObjectOutputStream(socket.getOutputStream());
            //发送两次数据
            os.writeObject(new TransportObject(2, "我是客户端1!"));
            os.writeObject(new TransportObject(3, "我是客户端2!"));
            // shutdownOutput():执行此方法,显示的告诉服务端发送完毕
            socket.shutdownOutput();
            //阻塞等待服务器响应
            is = new ObjectInputStream(socket.getInputStream());
            TransportObject transportObject = (TransportObject) is.readObject();
            System.out.println(transportObject.toString());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

执行结果(部分)

服务端已经启动...
执行一次响应..0
执行一次响应..1
执行一次响应..2
执行一次响应..3
执行一次响应..4
执行一次响应..5
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:3
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:2
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:3
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:2
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:4
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:4
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:0
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:0
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:1
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:1
执行一次响应..6
执行一次响应..7
执行一次响应..8
执行一次响应..9
执行一次响应..10
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:5
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:8
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:5
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:8
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:7
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:6
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:7
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:6
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:9
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:9
执行一次响应..11
执行一次响应..12
执行一次响应..13
执行一次响应..14
执行一次响应..15
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:10
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:11
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:12
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:45 CST 2017}任务标记:10
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:11
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:12
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:13
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:13
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:14
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:14
执行一次响应..16
执行一次响应..17
执行一次响应..18
执行一次响应..19
执行一次响应..20
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:15
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:16
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:18
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:18
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:17
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:16
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:46 CST 2017}任务标记:15
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:17
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:19
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:19
执行一次响应..21
执行一次响应..22
执行一次响应..23
执行一次响应..24
执行一次响应..25
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:21
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:20
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:21
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:22
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:47 CST 2017}任务标记:20
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:22
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:23
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:23
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:24
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:24
执行一次响应..26
执行一次响应..27
执行一次响应..28
执行一次响应..29
执行一次响应..30
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:26
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:28
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:26
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:28
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:27
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:25
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:27
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:48 CST 2017}任务标记:25
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:29
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:29
执行一次响应..31
执行一次响应..32
执行一次响应..33
执行一次响应..34
执行一次响应..35
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:30
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:31
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:32
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:31
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:49 CST 2017}任务标记:30
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:32
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:33
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:33
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:34
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:34
执行一次响应..36
执行一次响应..37
执行一次响应..38
执行一次响应..39
执行一次响应..40
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:36
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:38
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:36
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:38
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:37
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:35
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:50 CST 2017}任务标记:35
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:37
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:39
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:39
执行一次响应..41
执行一次响应..42
执行一次响应..43
执行一次响应..44
执行一次响应..45
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:41
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:42
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:40
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:42
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:43
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:43
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:51 CST 2017}任务标记:40
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:41
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:44
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:44
执行一次响应..46
执行一次响应..47
执行一次响应..48
执行一次响应..49
执行一次响应..50
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:53 CST 2017}任务标记:46
TransportObject{id=2, content='我是客户端1!', date=Fri Aug 18 21:45:52 CST 2017}任务标记:45
TransportObject{id=3, content='我是客户端2!', date=Fri Aug 18 21:45:53 CST 2017}任务标记:46