Java 客户端服务器范例
最近在面试,虽然学习了一些新的框架,但是可能问类似于客户端服务器模型,然后根据其设计,所以就根据面试内容梳理一下客户端服务器模型。
客户端基本思路:
1.创建Socket实例,设置端口和IP地址等
2.通过Socket实例,获取到流对象
3.通过流对象,向其中输入数据 ,并且在完成后实现关闭流。
(注意事情:1.需要进行异常处理 2.注意关闭流和Socket 3.低级流和高级流的关闭顺序)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | //客户端程序 package ServerSocket; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class ClientDome { public static void main(String[] args) { Socket socket = null ; OutputStream outputStream= null ; BufferedOutputStream bufferedOutputStream= null ; try { socket= new Socket( "localhost" , 6060 ); outputStream=socket.getOutputStream(); bufferedOutputStream = new BufferedOutputStream(outputStream); String str = "Client Dome ..... Are you ok" ; bufferedOutputStream.write(str.getBytes()); bufferedOutputStream.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { bufferedOutputStream.close(); outputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } |
服务器模型构建:
1.创建一个ServerSocket对象,进行端口监听。
2.while(true)重复监听
3.通过端口监听对象 获取Socket实例 并且获取到网络流
4.输出网络流数据 并且关闭流
(注意事情:端口监听一次 获取监听对象多次 低级流和高级流的关闭顺序)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | //首先这是单线程版本 package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerSocketDome { @SuppressWarnings ( "null" ) public static void main(String[] args) { // 1.建立监听 ServerSocket serverSocket = null ; InputStream inputStream = null ; BufferedInputStream bufferedInputStream = null ; @SuppressWarnings ( "unused" ) Socket socket = null ; try { serverSocket = new ServerSocket( 6060 ); while ( true ){ socket = serverSocket.accept(); inputStream = socket.getInputStream(); bufferedInputStream = new BufferedInputStream(inputStream); byte [] bytes= new byte [ 10 ]; int len= 0 ; while ((len=bufferedInputStream.read(bytes))!=- 1 ){ System.out.print( new String(bytes, 0 , len)); } } } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufferedInputStream!= null ){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } |
多线程版本怎么操作,这里即将引入多线程
服务器版本多线程主要是对于请求分线程操作 ,一次连接会单独分配线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; //为了应对面试需要 尝试根据自己思路写一个新的多线程版本试试 //其实多线程版本是根据单线程改进而来 //具体而言 多线程的服务器 是应对多条请求 不同线程进行处理 public class ServerSocketThreadDome { public static void main(String[] args) { //当然 主线程的端口监听是不能修改的 ServerSocket serverSocket = null ; //标准web服务器的端口是8080 int port= 6060 ; try { serverSocket= new ServerSocket(port); Socket socket= null ; while ( true ){ socket=serverSocket.accept(); new Thread( new Server(socket)).start(); } } catch (IOException e) { e.printStackTrace(); } finally { if (serverSocket!= null ){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //这里的多线程说白了 就是为了应对多条请求而处理的结果 //也就是客户端对象 class Server implements Runnable{ private Socket socket; public Server(Socket socket) { super (); this .socket = socket; } @Override public void run() { InputStream inputStream= null ; BufferedInputStream bufferedInputStream = null ; try { inputStream = socket.getInputStream(); bufferedInputStream= new BufferedInputStream(inputStream); byte [] bytes= new byte [ 1024 ]; int len= 0 ; while ((len=bufferedInputStream.read(bytes))!=- 1 ){ System.out.print( new String(bytes, 0 , len)); System.out.println( "当前线程:" +Thread.currentThread().getName()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (bufferedInputStream!= null ){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } |
那么我们引入线程池的概念 有时候面试可能会问线程池
package ServerSocket; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //首先大话一下线程池,线程池类似于中介结果,我需要的时候找中介借一些人过来 //不需要的时候中介自己回去 我不需要提供其他待遇等等 //就是传说中的国企或者大型企业的外包部门 public class ServerSocketPoolDome { public static void main(String[] args) { ServerSocket serverSocket = null; //标准web服务器的端口是8080 int port=6060; try { serverSocket=new ServerSocket(port); Socket socket=null; ExecutorService executorService =Executors.newCachedThreadPool(); while(true){ socket=serverSocket.accept(); executorService.execute(new ServerPool(socket)); } } catch (IOException e) { e.printStackTrace(); }finally{ if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //这里的多线程说白了 就是为了应对多条请求而处理的结果 //也就是客户端对象 class ServerPool implements Runnable{ private Socket socket; public ServerPool(Socket socket){ super(); this.socket = socket; } @Override public void run() { InputStream inputStream=null; BufferedInputStream bufferedInputStream =null; try { inputStream = socket.getInputStream(); bufferedInputStream=new BufferedInputStream(inputStream); byte[] bytes=new byte[1024]; int len=0; while((len=bufferedInputStream.read(bytes))!=-1){ System.out.print(new String(bytes, 0, len)); System.out.println("当前线程:"+Thread.currentThread().getName()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(bufferedInputStream!=null){ bufferedInputStream.close(); inputStream.close(); socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
线程池的使用很爽,接下来看看线程池的源码
1 2 3 4 5 6 | public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor( 0 , Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } //线程池创建一个缓冲的线程池<br>//也就设置线程数目 和 活动时间 以及具体执行的方式 |
恐惧源于无知,代码改变世界
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义