• Java 客户端服务器范例


    最近在面试,虽然学习了一些新的框架,但是可能问类似于客户端服务器模型,然后根据其设计,所以就根据面试内容梳理一下客户端服务器模型。

    客户端基本思路:

    1.创建Socket实例,设置端口和IP地址等

    2.通过Socket实例,获取到流对象

    3.通过流对象,向其中输入数据 ,并且在完成后实现关闭流。

    (注意事情:1.需要进行异常处理 2.注意关闭流和Socket 3.低级流和高级流的关闭顺序)

    //客户端程序
    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.输出网络流数据 并且关闭流

    (注意事情:端口监听一次 获取监听对象多次 低级流和高级流的关闭顺序)

    //首先这是单线程版本
    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();
    			}
    		}
    	}
    
    }
    

      多线程版本怎么操作,这里即将引入多线程

    服务器版本多线程主要是对于请求分线程操作 ,一次连接会单独分配线程

    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();
                }
            }
    
        }
        
    }

    线程池的使用很爽,接下来看看线程池的源码

    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
    //线程池创建一个缓冲的线程池
    //也就设置线程数目 和 活动时间 以及具体执行的方式

      

  • 相关阅读:
    Centos6.8下设置gitlab服务开机自启动,关闭防火墙开机自启动
    gitlab设置SSH key
    在centos6.8下安装gitlab遇到的坑
    recyclerView中的方法
    ListView中的方法
    tcp断开时分几步
    get,post区别
    cookie是什么,在什么地方会用到
    http和https的区别
    keystore是个嘛东西
  • 原文地址:https://www.cnblogs.com/ad-zhou/p/9824336.html
Copyright © 2020-2023  润新知