hello world

随笔 - 2, 文章 - 63, 评论 - 0, 引用 - 0
数据加载中……

如何编写多线程Socket程序

转自 http://blog.csdn.net/ooppookid/article/details/51711323


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

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

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

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

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

服务端代码

 1 import java.io.BufferedReader;
 2 import java.io.IOException;
 3 import java.io.InputStreamReader;
 4 import java.io.PrintWriter;
 5 import java.net.ServerSocket;
 6 import java.net.Socket;
 7 import java.util.concurrent.ExecutorService;
 8 import java.util.concurrent.Executors;
 9 
10 public class SocketThreadPoolDemoServer {
11 
12     private int port = 8000;
13 
14     private ServerSocket serverSocket;
15 
16     private ExecutorService executorService; // 连接池
17 
18     private final int POOL_SIZE = 1// 连接池大小 , 若为 1 时最多支持 2 线程
19 
20     public SocketThreadPoolDemoServer() throws Exception {
21         serverSocket = new ServerSocket(port);
22         executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);// 初始化线程池
23         System.out.println("waitting connet");
24 
25     }
26 
27     /**
28      *
29      * 接受连接
30      *
31      * @author sunjie at 2016年6月14日
32      *
33      */
34     public void service() {
35         Socket socket = null;
36         while (true) {
37             try {
38                 socket = serverSocket.accept();
39                 executorService.execute(new Handler(socket)); // 使用连接池
40                 // new Thread(new Handler(socket)).start();// 不使用连接池
41             } catch (IOException e) {
42                 e.printStackTrace();
43             }
44         }
45     }
46 
47     /**
48      *
49      * 线程类,负责维持与一个客户端的通信
50      *
51      * @author sunjie at 2016年6月14日
52      *
53      */
54     class Handler implements Runnable {
55 
56         private Socket socket = null;
57 
58         public Handler(Socket socket) {
59             this.socket = socket;
60         }
61 
62         @Override
63         public void run() {
64             System.out.println("new connection accepted:" + socket.getInetAddress() + ":" + socket.getPort());
65             try {
66                 BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
67                 PrintWriter writer = new PrintWriter(socket.getOutputStream());
68                 String msg = null;
69                 while ((msg = reader.readLine()) != null) {
70                     System.out.println("from " + socket.getInetAddress() + ":" + socket.getPort() + ", receive msg:"
71                             + msg);
72                     writer.println(msg);
73                     writer.flush();
74                     if ("close".equals(msg)) {
75                         break;
76                     }
77                 }
78             } catch (IOException e) {
79                 e.printStackTrace();
80             } finally {
81                 try {
82                     if (socket != null) {
83                         socket.close();
84                     }
85                 } catch (IOException e) {
86                     e.printStackTrace();
87                 }
88             }
89         }
90     }
91 
92     public static void main(String[] args) throws Exception {
93         new SocketThreadPoolDemoServer().service();
94     }
95 }
96 
97 

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

waitting connet…

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

 1 public class SocketDemoClient {
 2 
 3     private String host = "127.0.0.1";// 要发送给服务端的ip
 4 
 5     private int port = 8000;// 要发送给服务端的端口
 6 
 7     private Socket socket;
 8 
 9     public SocketDemoClient() throws Exception {
10         socket = new Socket(host, port);// 构造Socket客户端,并与连接服务端
11     }
12 
13     public void talk() throws IOException {
14         try {
15             BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
16             PrintWriter writer = new PrintWriter(socket.getOutputStream());
17             // 读取本地控制台的消息
18             BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
19             String msg = null;
20             while ((msg = localReader.readLine()) != null) {
21                 writer.println(msg);
22                 writer.flush();
23                 System.out.println("send msg:" + reader.readLine());
24                 if ("close".equals(msg)) {
25                     break;
26                 }
27             }
28         } catch (Exception e) {
29             e.printStackTrace();
30         } finally {
31             if (socket != null) {
32                 socket.close();
33             }
34         }
35     }
36 
37     public static void main(String[] args) throws Exception {
38         new SocketDemoClient().talk();
39     }
40 }

由于我们要测试多个客户端连接同一个服务端,所以我们需要多次运行客户端代码。这里我们运行两次之后(称为客户端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:好好学习天天向上

posted on 2017-07-25 10:30 听风 阅读(97) 评论(0)  编辑  收藏 所属分类: JAVA


只有注册用户登录后才能发表评论。


网站导航: