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

Java 客戶端服務器範例

sync ret ngs 實現 線程池 localhost 根據 輸入數據 lose

最近在面試,雖然學習了一些新的框架,但是可能問類似於客戶端服務器模型,然後根據其設計,所以就根據面試內容梳理一下客戶端服務器模型。

客戶端基本思路:

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

  

Java 客戶端服務器範例