带线程池的socket客户端与服务端
前言
socket(套接字),Socket和ServerSocket位于java.net包中,之前虽然对socket有过一些了解,但一直都是云里雾里的,特意仔细的学习了一个socket,用socket模拟一个天气查询的功能,并且解决了几个使用socket过程中比较严重的问题。
最简单的客户端和服务端
服务端代码
1 package cn.hucc.socket.server; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 /** 10 * 11 * @auth hucc 12 * @date 2015年10月10日 13 */ 14 public class WeatherServer { 15 16 private static final int PORT = 8888; 17 18 public static void main(String[] args) { 19 20 ServerSocket server = null; 21 Socket socket = null; 22 DataInputStream dataInputStream = null; 23 DataOutputStream dataOutputStream = null; 24 try { 25 server = new ServerSocket(PORT); 26 System.out.println("天气服务端已经移动,监听端口:" + PORT); 27 socket = server.accept(); 28 29 // 接受客户端请求 30 dataInputStream = new DataInputStream(socket.getInputStream()); 31 String request = dataInputStream.readUTF(); 32 System.out.println("from client..." + request); 33 34 // 响应客户端 35 dataOutputStream = new DataOutputStream(socket.getOutputStream()); 36 String response = "天气:晴朗,温度:36度"; 37 dataOutputStream.writeUTF(response); 38 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } finally { 42 try { 43 if (dataInputStream != null) { 44 dataInputStream.close(); 45 } 46 if (dataOutputStream != null) { 47 dataOutputStream.close(); 48 } 49 } catch (IOException e) { 50 e.printStackTrace(); 51 } 52 } 53 } 54 }
View Code
服务端代码很简单,这里没有直接使用InputStream和OutputStream两个流,而是使用了DataInputStream和DataOutputStream两个类,通过readUTF()和writeUTF()两个方法免去转码的痛苦。
客户端代码
1 package cn.hucc.socket.client; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.Socket; 7 8 /** 9 * 10 * @auth hucc 11 * @date 2015年10月10日 12 */ 13 public class WeatherClient { 14 private static final String HOST = "127.0.0.1"; 15 private static final int PORT = 8888; 16 17 public static void main(String[] args) { 18 19 Socket socket = null; 20 DataInputStream dataInputStream = null; 21 DataOutputStream dataOutputStream = null; 22 try { 23 socket = new Socket(HOST, PORT); 24 25 //给服务端发送请求 26 dataOutputStream = new DataOutputStream(socket.getOutputStream()); 27 String request = "北京"; 28 dataOutputStream.writeUTF(request); 29 30 dataInputStream = new DataInputStream(socket.getInputStream()); 31 String response = dataInputStream.readUTF(); 32 System.out.println(response); 33 34 } catch (IOException e) { 35 e.printStackTrace(); 36 }finally{ 37 try { 38 if(dataInputStream != null){ 39 dataInputStream.close(); 40 } 41 if(dataOutputStream != null){ 42 dataOutputStream.close(); 43 } 44 if(socket != null){ 45 socket.close(); 46 } 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 51 } 52 } 53 }
View Code
运行结果
客户端运行结果:
服务端运行结果:
结果分析
客户端和服务端都运行起来了,并且达到了天气查询的效果,但是服务端只服务了一次就停止了,这明显不符合需求,服务端应该响应完客户端之后,继续监听8888端口,等待下一个客户端的连接。
让服务端一直提供服务
将服务端的代码写入死循环中,一直监听客户端的请求。修改服务端的代码:
1 public static void main(String[] args) throws IOException { 2 3 ServerSocket server = null; 4 Socket socket = null; 5 DataInputStream dataInputStream = null; 6 DataOutputStream dataOutputStream = null; 7 server = new ServerSocket(PORT); 8 System.out.println("天气服务端已经移动,监听端口:" + PORT); 9 while(true){ 10 try { 11 socket = server.accept(); 12 13 // 接受客户端请求 14 dataInputStream = new DataInputStream(socket.getInputStream()); 15 String request = dataInputStream.readUTF(); 16 System.out.println("from client..." + request); 17 18 // 响应客户端 19 dataOutputStream = new DataOutputStream(socket.getOutputStream()); 20 String response = "天气:晴朗,温度:36度"; 21 dataOutputStream.writeUTF(response); 22 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } finally { 26 try { 27 if (dataInputStream != null) { 28 dataInputStream.close(); 29 } 30 if (dataOutputStream != null) { 31 dataOutputStream.close(); 32 } 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 } 37 } 38 }
View Code
通过while(true)死循环,服务端一直监听8888端口,由于socket是阻塞的,只有服务端完成了当前客户端的响应,才会继续处理下一个客户端的响应。这样一直让主线线程去处理socket请求不合适,因此需要为服务端加上多线程功能,同时处理多个socket请求。
给服务端加上多线程
修改代码,将服务端的socket处理抽取出来,并且封装到Runnable接口的run方法中。
1 package cn.hucc.socket.server; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.IOException; 6 import java.net.Socket; 7 8 /** 9 * 10 * @auth hucc 11 * @date 2015年10月10日 12 */ 13 public class WeatherThread extends Thread { 14 15 private Socket socket; 16 17 public WeatherThread(Socket socket){ 18 this.socket = socket; 19 } 20 21 public void run() { 22 23 DataInputStream dataInputStream = null; 24 DataOutputStream dataOutputStream = null; 25 try { 26 // 接受客户端请求 27 dataInputStream = new DataInputStream(socket.getInputStream()); 28 String request = dataInputStream.readUTF(); 29 System.out.println("from client..." + request+" 当前线程:"+Thread.currentThread().getName()); 30 31 // 响应客户端 32 dataOutputStream = new DataOutputStream(socket.getOutputStream()); 33 String response = "天气:晴朗,温度:36度"; 34 dataOutputStream.writeUTF(response); 35 36 } catch (IOException e) { 37 e.printStackTrace(); 38 } finally { 39 try { 40 if (dataInputStream != null) { 41 dataInputStream.close(); 42 } 43 if (dataOutputStream != null) { 44 dataOutputStream.close(); 45 } 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 } 50 } 51 }
View Code
修改服务端,添加多线程功能
1 package cn.hucc.socket.server; 2 3 import java.io.IOException; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 7 /** 8 * 9 * @auth hucc 10 * @date 2015年10月10日 11 */ 12 public class WeatherServer { 13 14 private static final int PORT = 8888; 15 16 public static void main(String[] args) throws IOException { 17 18 ServerSocket server = null; 19 Socket socket = null; 20 server = new ServerSocket(PORT); 21 System.out.println("天气服务端已经移动,监听端口:" + PORT); 22 while(true){ 23 socket = server.accept(); 24 new WeatherThread(socket).start(); 25 } 26 } 27 }
View Code
此时服务端已经拥有多线程处理能力了,运行结果如下图:
弊端分析
尽管服务端现在已经有了多线程处理能力,但是通过运行结果,我们可以看到,服务端每次接收到客户端的请求后,都会创建一个新的线程去处理,而jvm的线程数量过多是,服务端处理速度会变慢。而且如果并发较高的话,瞬间产生的线程数量也会比较大,因此,我们需要再给服务端加上线程池的功能。
给服务端加上线程池功能
使用java.util.concurrent.Executor类就可以创建一个简单的线程池,代码如下:
1 package cn.hucc.socket.server; 2 3 import java.io.IOException; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 import java.util.concurrent.Executor; 7 import java.util.concurrent.Executors; 8 9 /** 10 * 11 * @auth hucc 12 * @date 2015年10月10日 13 */ 14 public class WeatherServer { 15 16 private static final int PORT = 8888; 17 18 public static void main(String[] args) throws IOException { 19 20 ServerSocket server = null; 21 Socket socket = null; 22 server = new ServerSocket(PORT); 23 System.out.println("天气服务端已经移动,监听端口:" + PORT); 24 25 //FixedThreadPool最多开启3(参数)个线程,多余的线程会存储在队列中,等线程处理完了 26 //再从队列中获取线程继续处理 27 Executor executor = Executors.newFixedThreadPool(3); 28 while(true){ 29 socket = server.accept(); 30 executor.execute(new WeatherThread(socket)); 31 } 32 } 33 }
View Code
Executor一共有4种线程池实现,这里使用了FixedThreadPool最多开启3(参数)个线程,多余的线程会存储在队列中,等线程处理完了再从队列中获取,继续处理。这样的话无论并发量多大,服务端只会最多3个线程进行同时处理,使服务端的压力不会那么大。
运行结果:
通过运行结果,可以看到线程只开了1,2,3三个线程。
到这里,socket的简易教程便结束了。O(∩_∩)O~~
转载于:https://www.cnblogs.com/gnoc/p/4866788.html
带线程池的socket客户端与服务端相关推荐
- 基于半同步/半反应堆线程池实现的HTTP解析服务端程序
简介: 半同步/半反应堆线程池是通过一个线程往工作队列添加任务T,然后工作线程竞争工作队列获得任务T.HTTP请求解析服务端程序:逐行解析客户端发送来的HTTP请求然后作出HTTP回答.采用线程池就是 ...
- java socket同步_Java socket客户端与服务端同步通信实例
工作中没涉及有关JAVA SOCKET编程的实际经历,但理论大概了解.想正明一下自已的对JAVA SOCKET理解写个通信TEST,通过TEST验证了基本与理论相近.下面是TEST SRC CODE ...
- python客户端和服务端实验_python实现socket客户端和服务端简单示例
复制代码@H_301_3@ 代码如下: import socket #socket通信客户端 def client(): mysocket=socket.socket(socket.AF_INET,s ...
- android studio中使用AIDL进行客户端与服务端互相通信
前言 在AIDL实现IPC通信,调用远程服务端的方法.但是,远程服务端并不能主动给客户端返回信息.在很多情况下是需要远程服务端主动给客户端返回数据,客户端只需要进行监听即可,这是典型的观察者模式.这篇 ...
- 基于Socket实现客户端与服务端通讯
基于Socket实现客户端与服务端通讯 socket 概述 Socket,套接字就是两台主机之间逻辑连接的端点.TCP/IP协议是传输层协议,主要解决数据如何 在网络中传输,而HTTP是应用层协议,主 ...
- java网络编程Socket实现客户端向服务端发送信息
(可按目录按需阅读,我一般会整理的比较细) 前置知识 java IO Socket 什么是socket?socket字面意思其实就是一个插口或者套接字,包含了源ip地址.源端口.目的ip地址和源端口. ...
- php socket 握手,python Socket之客户端和服务端握手详细介绍
这篇文章主要为大家详细介绍了python Socket之客户端和服务端握手,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 简单的学习下利用socket来建立客户端和服务端之间的连接并且发送数据 1 ...
- php winform通信,C# Winform 通过Socket实现客户端和服务端TCP通信
操作界面如下: 1.声明Socket 第一个参数:寻址方式,第二个参数:传输数据的方式,第三个参数:通信协议 Socket socket = new Socket(AddressFamily.Inte ...
- OSI七层、TCP/IP五层、UDP、TCP的socket编程(服务端及客户端)、字节序转换、多进程以及多线程服务端的实现
1.网络以覆盖范围划分:局域网/城域网/广域网 互联网/因特网 以太网/令牌环网--组网方式 2.在网络中必须能够为一表示每一台主机,才能实现点到点的精确通信 IP地址: ...
最新文章
- varnish详解3
- Spring事件机制详解
- 服务器windows模拟linux环境,科学网—Windows不用虚拟机或双系统,轻松实现shell环境:gitforwindows - 刘永鑫的博文...
- leetcode 994.腐烂的橘子
- 解决tfs工作区绑定问题
- 「深入浅出」主流前端框架更新批处理方式
- Android开发在路上:少去踩坑,多走捷径
- jQuery:基础知识学习
- 如何使用商品历史价格查询网站
- android自定义网络请求框架,安卓快速开发框架(十九)XBaseAndroid Http网络请求
- vue3.0 watch监听器使用方法
- JAVA生成甘特图Excel导出
- JVM中栈的frames详解
- unity3D修改商店下载路径
- Xcode效率提升(快捷键等)
- 解决Identify and stop the process that‘s listening on port 8080 端口问题
- 根据经纬度,随机生成经纬度
- w32time服务自动更新时间(NTP)
- ioremap和mmap的区别
- 块存储,文件存储,对象存储的区别和理解
热门文章
- javascript window alert
- Flask Oauth
- Flask Middle
- matlab中常微分方法,MATLAB解常微分方程组的解法(好东西要共享)
- java设置文件为文件夹_如何为文件夹及其所有子文件夹和文件设置chmod? [关闭]...
- VCSA6.7 备份和还原
- 华为18级工程师三年心血终成趣谈网络协议文档(附大牛讲解)
- 使用计算机计算一个多边形,多边形面积计算器
- 差分电荷密度 matlab,差分电荷密度
- 如何查找cvpr类的论文_美国凯泽大学工商管理硕士:MBA论文案例编写类如何写?...