1. 程式人生 > >Java 客戶端伺服器範例

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>());
    }
//執行緒池建立一個緩衝的執行緒池
//也就設定執行緒數目 和 活動時間 以及具體執行的方式