运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接
运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接
最近在项目中可能要用到socket相关的东西来发送消息,所以初步研究了下socket的TCP和UDP实现方式,并且结合java1.5的concurrent.ExecutorService类来实现多线程。
具体实现方式见代码:
一、TCP方式:
1、服务端实现方式:
TCP的服务端实现方式主要用到ServerSocket类,接收等待客户端连接的方法是accept();
代码如下:类SocketServerTCP

1 private int port = 8823; 2 private ServerSocket serverSocket; 3 private ExecutorService executorService;// 线程池 4 private final int POOL_SIZE = 100;// 单个CPU线程池大小 5 6 public SocketServerTCP() { 7 try { 8 serverSocket = new ServerSocket(port); 9 executorService = Executors.newFixedThreadPool(Runtime.getRuntime() 10 .availableProcessors() * POOL_SIZE); 11 logger.info("端口号为" + port + "的服务器启动"); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 } 15 } 16 17 public void service() { 18 System.out.println("socket初始化成功!"); 19 logger.info("socket服务端初始化成功!"); 20 while (true) { 21 Socket socket = null; 22 try { 23 // 接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接 24 socket = serverSocket.accept(); 25 executorService.execute(new CallService(socket)); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 }

CallService类主要作用是接收到消息后,来实现具体业务。
代码如下:

1 /** 2 * 功能说明:执行具体业务的线程 3 */ 4 class CallService implements Runnable { 5 Logger logger = Logger.getLogger(CallService.class); 6 private Socket socket; 7 8 private BufferedReader is; 9 private PrintWriter os; 10 11 public CallService(Socket socket) { 12 this.socket = socket; 13 } 14 15 public void run() { 16 try { 17 is = new BufferedReader(new InputStreamReader(socket.getInputStream())); 18 os = new PrintWriter(socket.getOutputStream()); 19 20 String msg = is.readLine(); 21 22 System.out.println("接到客户端消息" + msg); 23 24 //返回消息给客户端 25 String responseMsg="服务端返回消息:" + msg; 26 os.println(responseMsg); 27 os.flush(); 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } finally { 31 try { 32 if (os != null) { 33 os.close(); 34 } 35 if (is != null) { 36 is.close(); 37 } 38 if (socket != null) { 39 socket.close(); 40 } 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 } 45 }

服务器启动方式:
1 public static void main(String[] args) { 2 new SocketServerTCP().service(); 3 }
2、TCP客户端实现代码
客户通过new Socket(ip, port)创建一个socket,并通过PrintWriter来向服务器发送消息

1 public class SocketClientTCP { 2 public String sendMsg(String ip, int port, String msg) { 3 Socket client = null; 4 try { 5 // 创建Socket 6 client = new Socket(ip, port); 7 8 // 向服务器发送消息 9 PrintWriter out = new PrintWriter(new BufferedWriter( 10 new OutputStreamWriter(client.getOutputStream())), true); 11 out.println(msg); 12 out.flush(); 13 14 // 接收来自服务器的消息 15 BufferedReader in = new BufferedReader(new InputStreamReader( 16 client.getInputStream())); 17 String str = in.readLine(); 18 // 关闭流 19 out.close(); 20 in.close(); 21 // 关闭Socket 22 client.close(); 23 return str; 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 return ""; 28 } 29 30 public static void main(String[] args) { 31 SocketClientTCP client = new SocketClientTCP(); 32 String str1 = client.sendMsg("127.0.0.1", 8823,"xiaoxi_1234567890A1234567!"); 33 System.out.println("str1=====" + str1); 34 } 35 }

二、UDP实现方式
1、“服务端”实现方式
UDP的服务端主要是用到DatagramSocket、DatagramPacket类,通过new DatagramSocket(port)来创建一个socket,并且通过DatagramPacket来接收消息 代码如下:类SocketServerUDP:

1 private int port = 1114; 2 private DatagramSocket dataSocket; 3 private ExecutorService executorService;// 线程池 4 private final int POOL_SIZE = 100;// 单个CPU线程池大小 5 6 public SocketServerUDP() { 7 try { 8 dataSocket = new DatagramSocket(port); 9 executorService = Executors.newFixedThreadPool(Runtime.getRuntime() 10 .availableProcessors() * POOL_SIZE); 11 logger.info("端口号为" + port + "的服务器启动"); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 } 15 } 16 17 public void service() { 18 System.out.println("socket初始化成功!"); 19 logger.info("socket服务端初始化成功!"); 20 21 while (true) { 22 try { 23 byte[] buff = new byte[128];// 传输消息不超过64字 24 DatagramPacket dataPacket = new DatagramPacket(buff, buff.length); 25 dataSocket.receive(dataPacket);// 等待接收来自客户端的数据包 26 27 executorService.execute(new UdpCallService(dataPacket));//接收到消息后执行具体的业务 28 } catch (Exception e) { 29 e.printStackTrace(); 30 } 31 } 32 }

UDPCallService类主要作用是接收到消息后,来实现具体业务。
代码如下:

1 class UdpCallService implements Runnable { 2 Logger logger = Logger.getLogger(UdpCallService.class); 3 private DatagramPacket packet; 4 private DatagramSocket dataSocket; 5 6 public UdpCallService(DatagramPacket packet) { 7 try { 8 this.packet = packet; 9 // 创建本机可以端口的DatagramSocket 10 dataSocket = new DatagramSocket(); 11 } catch (SocketException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 public void run() { 17 String str=new String(packet.getData()); 18 System.out.println("接收到消息:"+str); 19 //返回数据给客户端 20 responeSocket("UDP消息返回:"+str); 21 } 22 23 //返回消息给客户端 24 public void responeSocket(String message){ 25 // 构造响应数据包 26 byte[] response = message.toString().getBytes(); 27 DatagramPacket dataPacket = new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort()); 28 try {// 发送 29 dataSocket.send(dataPacket); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 }

服务器启动方式:
1 public static void main(String[] args) { 2 new SocketServerUDP().service(); 3 }
2、UDP客户端实现方式
UDP客户端的实现方式与"服务端"实现方式差不多,因为UDP本身就没有很严格的服务端和客户端定义。
代码如下:

1 public class SocketClientUDP { 2 3 private int PORT; 4 5 public SocketClientUDP(int PORT) { 6 this.PORT=PORT; 7 } 8 9 public String getMessage() { 10 String msg = ""; 11 try { 12 13 String str = "hello world "; 14 DatagramSocket socket = new DatagramSocket(); 15 16 // 发送UPD消息给服务端 17 DatagramPacket requestPacket = new DatagramPacket(str.getBytes(), 18 str.length(), InetAddress.getLocalHost(), PORT); 19 socket.send(requestPacket); 20 21 // 接收服务端返回的UDP消息 22 byte[] data = new byte[128]; 23 DatagramPacket responsePacket = new DatagramPacket(data,data.length); 24 socket.receive(responsePacket); 25 msg = new String(responsePacket.getData(), 0,responsePacket.getLength()); 26 socket.close(); 27 } catch (UnknownHostException e) { 28 System.err.println("Exception: host could not be found"); 29 } catch (Exception e) { 30 System.err.println("Exception: " + e); 31 e.printStackTrace(); 32 } 33 return msg; 34 } 35 36 public static void main(String[] args){ 37 SocketClientUDP clientUdp = new SocketClientUDP(1114); 38 String str1= clientUdp.getMessage(); 39 System.out.println("str1====="+str1); 40 }

具体的JAVA文件下载地址:
运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接的更多相关文章
- java.util.concurrent.RejectedExecutionException 线程池饱和
java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPoli ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法
jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口 |–Execut ...
- 转:java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例
java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例 1.CountDownLatch:一个同步工具类,它允许一个或多个线程一 ...
- 并发编程-concurrent指南-线程池ExecutorService的实例
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- java android ExecutorService 线程池解析
ExecutorService: 它也是一个接口,它扩展自Executor接口,Executor接口更像一个抽象的命令模式,仅有一个方法:execute(runnable);Executor接口简单, ...
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...
- java之并发编程线程池的学习
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. java.uitl.concurrent.Thre ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
随机推荐
- BFPRT算法(求第K小的数字)
BFPRT算法: 1.介绍: BFPRT算法又叫中位数的中位数算法,主要用于在无序数组中寻找第K大或第K小的数,它的最坏时间复杂度为O(n),它是由Blum,Floyd,Pratt,Rivest,Ta ...
- video.js 视频自动全屏播放
1.头部引用脚本 <link href="css/video-js.min.css" rel="stylesheet"> <link href ...
- 洛谷1514 引水入域 dp+记忆化搜索
题目链接:https://www.luogu.com.cn/problem/P1514 题意大致是:给定一个(n,m)的数值矩阵,可以在第一行建造水库,如果一个格子周围的某格子值小于它,那水就可以流到 ...
- RNN,GRU,LSTM
2019-08-29 17:17:15 问题描述:比较RNN,GRU,LSTM. 问题求解: 循环神经网络 RNN 传统的RNN是维护了一个隐变量 ht 用来保存序列信息,ht 基于 xt 和 ht- ...
- 一夜搞懂 | JVM GC&内存分配
前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 学习导图 一.为什么要学习GC&内存分配? 时代发展到现在,如今的内存动态分配与内存回收技术已经相当成 ...
- java split方法使用注意事项
在java.lang包中有String.split()方法,返回是一个数组. 使用时要注意参数如果是特殊符号的话要进行转义. 1."."和"|"都是转义字符,必 ...
- 谷歌开发者:看可口可乐公司是怎么玩转 TensorFlow 的?
在这篇客座文章中,可口可乐公司的 Patrick Brandt 将向我们介绍他们如何使用 AI 和 TensorFlow 实现无缝式购买凭证. 可口可乐的核心忠诚度计划于 2006 年以 MyCoke ...
- 4 Values whose Sum is 0 POJ - 2785(二分应用)
题意:输入一个数字n,代表有n行a,b,c,d,求a+b+c+d=0有多少组情况. 思路:先求出前两个数字的所有情况,装在一个数组里面,再去求后两个数字的时候二分查找第一个大于等于这个数的位置和第一个 ...
- 一、配置Ubuntu网络设置大纲
root@ubuntu:为我的Ubuntu系统,即 用户名@主机名: 1.改主机名 ifconfig查询本机IP地址vim /etc/hostname进入i编辑更改,改完按esc键 然后:wq!保存 ...
- [JZOJ5343]健美猫<模拟>
[思路] 这个是一个非常容易看出来的模拟,但是模拟也是有技巧的 一般人的模拟思路一般就是移动元素或者下标 然后我就看到了一个有趣的思路 建立坐标轴 以i坐标为横坐标,以si为纵坐标,然后画一条斜率为1 ...