java socket同步异步通信_java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型...

同步I/O模型的弊端

===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机

伪异步I/O的弊端分析

===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情

(1)有数据可读

(2)可用数据已经读取完毕

(3)发生空指针或者I/O异常

===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。在阻塞期间,其他接入的消息只能在消息队列中排队。

===>伪异步I/O实际上仅仅只是对之前I/O线程模型的一个简单优化,它无法从根本上解决同步I/O导致的通信线程阻塞问题,下面我们简单分析下如果通信对方返回应答时间过长,会引起的级联鼓掌。

(1)服务端处理缓慢,返回应答消息耗费60s,平时只需要10ms

(2)采用伪异步I/O线程正在读取故障服务节点的响应,由于读取输入流是阻塞的。因此,它将会被同步阻塞60s

(3)假如所有的可用线程都被故障服务器阻塞,那后续所有的I/O消息都将在队列中排队。

(4)由于线程池采用阻塞队列实现,当队列积满之后,后续入队列的操作将被阻塞

(5)由于前端只有一个Accptor线程接收客户端接入,它被阻塞在线程池的同步阻塞队列之后,新的客户端请求消息将被拒绝,客户端会发生大量的连接超时。

(6)由于几乎所有的链接都超时,调用者会认为系统崩溃,无法接收新的请求消息。

【一】同步阻塞I/O服务端通信模型

217ae5dee7ea73e4f7bd97a415772237.png

第一:socket同步阻塞服务器的启动

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.IOException;4 importjava.net.ServerSocket;5 importjava.net.Socket;6

7 /**

8 * 时间服务器9 * 基于同步阻塞I/O实现的服务器模型10 *@authorsxf11 *12 */

13 public classTimerServer {14

15 /**

16 * 启动timerServer服务器17 */

18 public voidinit(){19 int port=8000;20 //创建Socket服务

21 ServerSocket server=null;22 try{23 server=newServerSocket(port);24 System.out.println("TimerServer.init()===>the time server is start in port"+port);25 Socket socket=null;26 while(true){27 //获取一次socket请求

28 socket=server.accept();29 //启动一个新线程处理socket请求

30 new Thread(newTimerServerHandler(socket)).start();31 }32 } catch(IOException e) {33 e.printStackTrace();34 }finally{35 if(server!=null){36 try{37 server.close();38 } catch(IOException e) {39 //TODO Auto-generated catch block

40 e.printStackTrace();41 }42 }43 server=null;44 }45

46 }47

48

49 public static voidmain(String[] args) {50 //启动timerServer服务

51 TimerServer timerServer=newTimerServer();52 timerServer.init();53 }54 }

View Code

第二:soket服务器接收到请求的处理类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6 importjava.io.PrintWriter;7 importjava.net.Socket;8 importjava.util.Date;9

10 /**

11 * 时间服务器接受socket请求的处理类12 *@authorsxf13 * 继承Runnable接口的线程类14 *15 */

16 public class TimerServerHandler implementsRunnable {17

18 privateSocket socket;19

20 publicTimerServerHandler(Socket socket) {21 this.socket=socket;22 }23

24 /**

25 * 处理socket请求的线程体26 */

27 @Override28 public voidrun() {29 BufferedReader in=null;30 PrintWriter out=null;31 try{32 //获取请求的输入流

33 in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));34 //获取响应请求的输出流

35 out=new PrintWriter(this.socket.getOutputStream(),true);36

37 String currentTime=null;38 String body=null;39 //读取请求输入流的内容获取请求信息

40 while(true){41 body=in.readLine();42 if(body==null){43 break;44 }45 //打印请求信息

46 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);47

48 //处理请求信息

49 if("shangxiaofei".equals(body)){50 currentTime=newDate(System.currentTimeMillis()).toString();51 }else{52 currentTime="you is not get time";53 }54 //响应请求信息

55 out.println(currentTime);56 }57

58 } catch(IOException e) {59 e.printStackTrace();60 }finally{61 if(in!=null){62 try{63 in.close();64 } catch(IOException e) {65 //TODO Auto-generated catch block

66 e.printStackTrace();67 }68 }69

70 if(out!=null){71 out.close();72 }73

74 if(this.socket!=null){75 try{76 socket.close();77 } catch(IOException e) {78 //TODO Auto-generated catch block

79 e.printStackTrace();80 }81 }82

83 this.socket=null;84 }85

86

87

88

89 }90

91 }

View Code

第三:向socket服务器发送请求

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6 importjava.io.PrintWriter;7 importjava.net.Socket;8

9 /**

10 * 创建一个客户端请求11 *@authorsxf12 *13 */

14 public classTimerClient {15

16

17

18 public static voidmain(String[] args) {19 int port=8000;20 Socket socket=null;21 BufferedReader in=null;22 PrintWriter out=null;23 try{24 socket=new Socket("127.0.0.1",port);25 in=new BufferedReader(newInputStreamReader(socket.getInputStream()));26 out=new PrintWriter(socket.getOutputStream(),true);27 //发送请求

28 out.println("shangxiaofei!=");29 System.out.println("TimerClient.main()send order to server success");30

31 //等待服务器响应

32 String resp=in.readLine();33 System.out.println("TimerClient.main(Now is:)"+resp);34 } catch(Exception e) {35 //TODO Auto-generated catch block

36 e.printStackTrace();37 }finally{38 if(out!=null){39 out.close();40 out=null;41 }42 if(in !=null){43 try{44 in.close();45 } catch(IOException e) {46 //TODO Auto-generated catch block

47 e.printStackTrace();48 }49 in=null;50 }51

52 if(socket!=null){53 try{54 socket.close();55 } catch(IOException e) {56 //TODO Auto-generated catch block

57 e.printStackTrace();58 }59 }60 }61 }62

63 }

View Code

【二】同步阻塞I/O服务端通信模型构造的伪异步通信模型

58f613b21a99d75f1c4b40346ff6b25b.png

一:伪异步socket服务端启动(就是在同步的基础上使用了线程池)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.IOException;4 importjava.net.ServerSocket;5 importjava.net.Socket;6

7 /**

8 * 时间服务器9 * 基于同步阻塞I/O实现的服务器模型10 *@authorsxf11 *12 */

13 public classTimerServer {14

15 /**

16 * 启动timerServer服务器17 */

18 public voidinit(){19 int port=8000;20 //创建Socket服务

21 ServerSocket server=null;22 try{23 server=newServerSocket(port);24 System.out.println("TimerServer.init()===>the time server is start in port"+port);25 Socket socket=null;26 //创建处理socket请求的线程池

27 TimerServerHandlerExcetorPool pool=new TimerServerHandlerExcetorPool(50, 10000);28

29 while(true){30 //获取一次socket请求

31 socket=server.accept();32 //将请求任务提交到线程池处理

33 pool.execute(newTimerServerHandler(socket));34 }35 } catch(IOException e) {36 e.printStackTrace();37 }finally{38 if(server!=null){39 try{40 server.close();41 } catch(IOException e) {42 //TODO Auto-generated catch block

43 e.printStackTrace();44 }45 }46 server=null;47 }48

49 }50

51

52 public static voidmain(String[] args) {53 //启动timerServer服务

54 TimerServer timerServer=newTimerServer();55 timerServer.init();56 }57 }

View Code

二:伪异步socket服务处理socket请求的线程池

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.util.concurrent.ArrayBlockingQueue;4 importjava.util.concurrent.ExecutorService;5 importjava.util.concurrent.ThreadPoolExecutor;6 importjava.util.concurrent.TimeUnit;7 /**

8 * 处理socket服务器接收到的socket请求的线程池9 *@authorsxf10 *11 */

12 public classTimerServerHandlerExcetorPool {13

14 privateExecutorService executorService;15

16 /**

17 * 初始化线程池18 *@parammaxPoolSize19 *@paramqueueSize20 */

21 public TimerServerHandlerExcetorPool(int maxPoolSize,intqueueSize){22 executorService=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue(queueSize));23 }24

25 /**

26 * 提交到线程池,执行socket请求任务27 *@paramrunnable28 */

29 public voidexecute(Runnable runnable){30 executorService.execute(runnable);31 }32

33 }

View Code

三:处理请求的Handler类(线程类)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6 importjava.io.PrintWriter;7 importjava.net.Socket;8 importjava.util.Date;9

10 /**

11 * 时间服务器接受socket请求的处理类12 *@authorsxf13 * 继承Runnable接口的线程类14 *15 */

16 public class TimerServerHandler implementsRunnable {17

18 privateSocket socket;19

20 publicTimerServerHandler(Socket socket) {21 this.socket=socket;22 }23

24 /**

25 * 处理socket请求的线程体26 */

27 @Override28 public voidrun() {29 BufferedReader in=null;30 PrintWriter out=null;31 try{32 //获取请求的输入流

33 in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));34 //获取响应请求的输出流

35 out=new PrintWriter(this.socket.getOutputStream(),true);36

37 String currentTime=null;38 String body=null;39 //读取请求输入流的内容获取请求信息

40 while(true){41 body=in.readLine();42 if(body==null){43 break;44 }45 //打印请求信息

46 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);47

48 //处理请求信息

49 if("shangxiaofei".equals(body)){50 currentTime=newDate(System.currentTimeMillis()).toString();51 }else{52 currentTime="you is not get time";53 }54 //响应请求信息

55 out.println(currentTime);56 }57

58 } catch(IOException e) {59 e.printStackTrace();60 }finally{61 if(in!=null){62 try{63 in.close();64 } catch(IOException e) {65 //TODO Auto-generated catch block

66 e.printStackTrace();67 }68 }69

70 if(out!=null){71 out.close();72 }73

74 if(this.socket!=null){75 try{76 socket.close();77 } catch(IOException e) {78 //TODO Auto-generated catch block

79 e.printStackTrace();80 }81 }82

83 this.socket=null;84 }85

86

87

88

89 }90

91 }

View Code

四:客户端发送请求

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.testbio;2

3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStreamReader;6 importjava.io.PrintWriter;7 importjava.net.Socket;8

9 /**

10 * 创建一个客户端请求11 *@authorsxf12 *13 */

14 public classTimerClient {15

16

17

18 public static voidmain(String[] args) {19 int port=8000;20 Socket socket=null;21 BufferedReader in=null;22 PrintWriter out=null;23 try{24 socket=new Socket("127.0.0.1",port);25 in=new BufferedReader(newInputStreamReader(socket.getInputStream()));26 out=new PrintWriter(socket.getOutputStream(),true);27 //发送请求

28 out.println("shangxiaofei!=");29 System.out.println("TimerClient.main()send order to server success");30

31 //等待服务器响应

32 String resp=in.readLine();33 System.out.println("TimerClient.main(Now is:)"+resp);34 } catch(Exception e) {35 //TODO Auto-generated catch block

36 e.printStackTrace();37 }finally{38 if(out!=null){39 out.close();40 out=null;41 }42 if(in !=null){43 try{44 in.close();45 } catch(IOException e) {46 //TODO Auto-generated catch block

47 e.printStackTrace();48 }49 in=null;50 }51

52 if(socket!=null){53 try{54 socket.close();55 } catch(IOException e) {56 //TODO Auto-generated catch block

57 e.printStackTrace();58 }59 }60 }61 }62

63 }

View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值