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>//也就设置线程数目 和 活动时间 以及具体执行的方式

  

posted @   coder-zhou  阅读(2436)  评论(0编辑  收藏  举报
编辑推荐:
· .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 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示