Java千百问_02基本使用(012)_如何编写多线程Socket程序

来源:互联网 发布:手机数据恢复软件安卓 编辑:程序博客网 时间:2024/05/22 03:41

点击进入_更多_Java千百问

1、如何编写多线程Socket程序

了解Socket看这里:Socket是什么
多线程Socket与单线程类似,只是使用了多线程的方式来管理连接,主线程负责接收连接,在接到连接后变创建新的线程,每个线程负责与自己的客户端进行通信。

了解单线程Socket看这里:如何编写单多线程Socket程序

与单线程Socket例子相比来说,服务端可以与多个客户端进行通信了,不过多线程频繁的创建与销毁便会带来很大的资源开销,而系统的网络资源等都是有限的。因此一般会引入线程池,可以在某种程度上重用线程,减少线程的创建和销毁的次数以减少开销

我们的代码也分为客户端和服务端两部分。服务端的代码中包含了使用和不使用线程池的两种方式。

服务端代码

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class SocketThreadPoolDemoServer {    private int port = 8000;    private ServerSocket serverSocket;    private ExecutorService executorService; // 连接池    private final int POOL_SIZE = 1; // 连接池大小 , 若为 1 时最多支持 2 线程    public SocketThreadPoolDemoServer() throws Exception {        serverSocket = new ServerSocket(port);        executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);// 初始化线程池        System.out.println("waitting connet...");    }    /**     *     * 接受连接     *     * @author sunjie at 2016年6月14日     *     */    public void service() {        Socket socket = null;        while (true) {            try {                socket = serverSocket.accept();                executorService.execute(new Handler(socket)); // 使用连接池                // new Thread(new Handler(socket)).start();// 不使用连接池            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     *     * 线程类,负责维持与一个客户端的通信     *     * @author sunjie at 2016年6月14日     *     */    class Handler implements Runnable {        private Socket socket = null;        public Handler(Socket socket) {            this.socket = socket;        }        @Override        public void run() {            System.out.println("new connection accepted:" + socket.getInetAddress() + ":" + socket.getPort());            try {                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));                PrintWriter writer = new PrintWriter(socket.getOutputStream());                String msg = null;                while ((msg = reader.readLine()) != null) {                    System.out.println("from " + socket.getInetAddress() + ":" + socket.getPort() + ", receive msg:"                            + msg);                    writer.println(msg);                    writer.flush();                    if ("close".equals(msg)) {                        break;                    }                }            } catch (IOException e) {                e.printStackTrace();            } finally {                try {                    if (socket != null) {                        socket.close();                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public static void main(String[] args) throws Exception {        new SocketThreadPoolDemoServer().service();    }}

运行服务端代码后,程序会一直进行监听,直到接收到客户端请求为止。结果如下:

waitting connet…

客户端代码(与单线程完全相同):

public class SocketDemoClient {    private String host = "127.0.0.1";// 要发送给服务端的ip    private int port = 8000;// 要发送给服务端的端口    private Socket socket;    public SocketDemoClient() throws Exception {        socket = new Socket(host, port);// 构造Socket客户端,并与连接服务端    }    public void talk() throws IOException {        try {            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));            PrintWriter writer = new PrintWriter(socket.getOutputStream());            // 读取本地控制台的消息            BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));            String msg = null;            while ((msg = localReader.readLine()) != null) {                writer.println(msg);                writer.flush();                System.out.println("send msg:" + reader.readLine());                if ("close".equals(msg)) {                    break;                }            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if (socket != null) {                socket.close();            }        }    }    public static void main(String[] args) throws Exception {        new SocketDemoClient().talk();    }}

由于我们要测试多个客户端连接同一个服务端,所以我们需要多次运行客户端代码。这里我们运行两次之后(称为客户端1、客户端2),查看服务端的Console,会出现以下结果,说明已经连接成功:

waitting connet…
new connection accepted:/127.0.0.1:59593
new connection accepted:/127.0.0.1:59596

我们在去客户端1的Console中输入我们要发送的消息”维护世界和平”,回车确定后,客户端1的Console出现以下结果,消息已经发出:

send msg:维护世界和平

再去客户端2的Console中输入”好好学习天天向上”,回车确定后,客户端2的Console出现以下结果,消息已经发出:

send msg:好好学习天天向上

在服务端的Console中,我们会看到如下结果,说明两个客户端的消息已经被接受

waitting connet…
new connection accepted:/127.0.0.1:59593
new connection accepted:/127.0.0.1:59596
from /127.0.0.1:59593, receive msg:维护世界和平
from /127.0.0.1:59596, receive msg:好好学习天天向上

0 0
原创粉丝点击