码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-06-19 11:40:45      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:

点击进入_更多_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:好好学习天天向上

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

标签:

原文地址:http://blog.csdn.net/ooppookid/article/details/51711323

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!