运用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文件下载地址:

http://files.cnblogs.com/fbsk/Socket_TCP_UDP.zip

时间: 2024-10-12 08:12:02

运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接的相关文章

Java多线程-新特性-线程池

Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要. 有关Java5线程新特征的内容全部在java.util.concurrent下面,里面包含数目众多的接口和类,熟悉这部分API特征是一项艰难的学习过程.目前有关这方面的资料和书籍都少之又少,大部分介绍线程方面书籍还停留在java5之前的知识层面上. 在Java5之

【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–ExecutorService:Executor的子接口,线程池的主要接口  |–ThreadPoolExecutor:ExecutorService的实现类  |–ScheduledExecutorService:ExecutorService的子接口,负责线程的调度  |–ScheduledThreadPo

java android ExecutorService 线程池解析

ExecutorService: 它也是一个接口,它扩展自Executor接口,Executor接口更像一个抽象的命令模式,仅有一个方法:execute(runnable);Executor接口简单,可是非常重要,重要在这样的设计的模式上..Java5以后,通过Executor来启动线程比用Thread的start()更好.在新特征中,能够非常easy控制线程的启动.运行和关闭过程,还能够非常easy使用线程池的特性. 几种不同的ExecutorService线程池对象 1.newCachedT

Handler+ExecutorService(线程池)+MessageQueue模式+缓存模式

android线程池的理解,晚上在家无事 预习了一下android异步加载的例子,也学习到了一个很重要的东东 那就是线程池+缓存  下面看他们的理解. [size=1.8em]Handler+Runnable模式 我们先看一个并不是异步线程加载的例子,使用 Handler+Runnable模式. 这里为何不是新开线程的原因请参看这篇文章:Android Runnable 运行在那个线程 这里的代码其实是在UI 主线程中下载图片的,而不是新开线程. 我们运行下面代码时,会发现他其实是阻塞了整个界面

Java 并发编程之线程池的使用 (二)

设置线程池的大小 如果线程池过大,那么可能会耗尽资源 ,如果过小,那么 将导致许多空闲的处理器无法工作,从而降低吞吐率. 要设置正确的线程池大小,需要分析计算环境,资源预算和任务的特性,cpu数量,内存大小,任务是计算密集型还是I/O密集型,还是二者皆可.它们是否需要像JDBC连接这样的稀缺资源,下面给出一个计算公式 N(threads)=N(cpu)*U(cpu)*(1+w/c); N(threads)是最后得到的结果大小 . N(cpu)是cpu数量,我的电脑是双核四线程,cpu的数量会是4

Java 并发编程之线程池的使用

在任务与执行策略之间的隐性耦合 Executor框架可以将任务的提交与任务的执行策略解耦开来(就是独立化).虽然Executor框架为制定和修改执行策略都提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略 比如: 依赖性任务 比如依赖于执行时序,执行结果或者其他效果,那么任务就带有隐含的依赖性.此时必须小心 地维持这些执行策略以避免产生活跃性问题(死锁等造成执行困难的问题) 使用线程封闭机制的任务 与线程池相比,单线程的Executor能够对并发性做出更强的承诺,它们能确保任务不会并发

Java多线程系列--“JUC线程池”03之 线程池原理(二)

线程池示例 在分析线程池之前,先看一个简单的线程池示例. import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolDemo1 { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThre

Java多线程——Executors和线程池

线程池的概念与Executors类的应用 1.创建固定大小的线程池 package java_thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ThreadPoolTest { /** * @param args */ public static void mai

Java并发编程:线程池的使用

在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,