1. 程式人生 > 實用技巧 >P2580 於是他錯誤的點名開始了(字典樹)

P2580 於是他錯誤的點名開始了(字典樹)

實現TCP程式,一個是ServerSocket類,用於表示伺服器端,一個是Socket類,用於表示客戶端

通訊時,首先建立代表伺服器端的ServerSocket物件,該物件相當於開啟一個服務,並等待客戶端的連線,然後建立代表客戶端的Socket物件向伺服器端發出連線請求,伺服器端響應請求,兩者建立連線開始通訊。

1.1ServerSocket

首先需要建立伺服器端程式

使用該構造方法在建立ServerSocket物件時,就可以將其繫結到一個指定的埠號上(引數port就是埠號)。

//伺服器物件
    ServerSocket server=new ServerSocket(9999);
    
//和客戶端建立連線, Socket socket=server.accept();

1.1Socket

ServerSocket物件可以實現服務端程式,但只實現伺服器端程式還不能完成通訊,此時還需要一個客戶端程式與之互動,為此JDK提供了一個Socket類,用於實現TCP客戶端程式

使用該構造方法在建立Socket物件時,會根據引數去連線在指定地址和埠上執行的伺服器程式,其中引數host接收的是一個字串型別的IP地址。

方法宣告

功能描述

int getPort()

該方法返回一個int型別物件,該物件是Socket物件與伺服器端連線的埠號

InetAddressgetLocalAddress()

該方法用於獲取Socket物件繫結的本地IP地址,並將IP地址封裝成InetAddress型別的物件返回

void close()

該方法用於關閉Socket連線,結束本次通訊。在關閉socket之前,應將與socket相關的所有的輸入/輸出流全部關閉,這是因為一個良好的程式應該在執行完畢時釋放所有的資源

InputStream getInputStream()

該方法返回一個InputStream型別的輸入流物件,如果該物件是由伺服器端的Socket返回,就用於讀取客戶端傳送的資料,反之,用於讀取伺服器端傳送的資料

OutputStream getOutputStream()

該方法返回一個OutputStream型別的輸出流物件,如果該物件是由伺服器端的Socket返回,就用於向客戶端傳送資料,反之,用於向伺服器端傳送資料

實現TCP 伺服器程式

* 表示伺服器程式的類 java.net.ServerSocket

* 構造方法:

* ServerSocket(int port)傳遞埠號

* 很重要的事情:必須要獲得客戶端的套接字物件Socket

* Socket accept()

*

* 1,建立伺服器ServerSocket物件(指定伺服器埠號)

* 2,開啟伺服器了,等待客戶端的連線,當客戶端連線後,可以獲取到連線伺服器的客戶端Socket物件

* 3,給客戶端反饋資訊

* 4,關閉流資源

public class TCPServer {
public static void main(String[] args) throws IOException {
    //建立伺服器ServerSocket物件(指定伺服器埠號)
    ServerSocket server=new ServerSocket(9999);
    //和客戶端建立連線,    開啟伺服器了,等待客戶端的連線,當客戶端連線後,可以獲取到連線伺服器的客戶端Socket物件
    Socket socket=server.accept();
    //接收客戶端傳送資料
    InputStream in=socket.getInputStream();
    byte[] bytes=new byte[1024];
    //獲取客戶端傳送的資料
    int len=in.read(bytes);
    //獲取ip
    String ip=socket.getInetAddress().getHostAddress();
    System.out.println("ip地址為:"+ip+"客戶端傳送的資料為"+new String(bytes,0,len));
    //回覆客戶端
    //獲取位元組輸出流
    OutputStream out=socket.getOutputStream();
    //向客戶端傳送資料
    out.write("收到".getBytes());
    //釋放資源
    server.close();
}
}

實現TCP 客戶端,連線到伺服器


* 和伺服器實現資料交換


* 實現TCP客戶端程式的類 java.net.Soket


* 構造方法


* Socket(String host,int port) 傳遞伺服器IP和埠號


* 注意:構造方法只要執行,就會和伺服器進行連線,連線失敗,丟擲異常



* OutputStream getOutputStream() 返回套接字的輸出流


* 作用:將資料輸出,輸出到伺服器


* InputStream getInputStream() 返回套接字的輸入流


* 作用:從伺服器端讀取資料



* 客戶端伺服器資料交換,必須使用套接字物件Socket中的獲取的IO流,自己new流,不行



* 1,建立客戶端Socket物件,(指定要連線的伺服器地址與埠號)


* 2,獲取伺服器端的反饋回來的資訊


* 3,關閉流資源

實現客戶端伺服器程式

//客戶端TCP
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
    //建立客戶端Socket物件,(指定要連線的伺服器地址與埠號)
    Socket socket=new Socket("127.0.0.1",9999);
    //獲取位元組輸出流,向客戶端傳送資料
    OutputStream out=socket.getOutputStream();
    out.write("你好".getBytes());
        //接收伺服器端的回覆
    //獲取位元組輸入流
    InputStream in=socket.getInputStream();
    byte[] bytes=new byte[1024];
    //把流中的資料儲存到陣列中,並記錄讀取位元組的個數
    int len=in.read(bytes);
    //獲取ip地址
    String ip=socket.getInetAddress().getHostAddress();
    System.out.println("ip為"+ip+"內容"+new String(bytes,0,len));
    
    socket.close();//釋放資源
        
}
}

檔案上傳

/*

* TCP上傳伺服器

  1. ServerSocket套接字物件,監聽埠8888
  2. 方法accept()獲取客戶端的連線物件
  3. 客戶端連線物件獲取位元組輸入流,讀取客戶端傳送圖片
  4. 建立File物件,繫結上傳資料夾

判斷資料夾存在,不存在,再建立資料夾

  1. 建立位元組輸出流,資料目的File物件所在資料夾
  2. 位元組讀取圖片,位元組流將圖片寫入到目的資料夾中
  3. 將上傳成功返回客戶端
  4. 關閉資源

*/

public class TCPServer {
public static void main(String[] args) throws IOException {
    //建立伺服器物件,明確埠號
    ServerSocket server=new ServerSocket(9999);
    //創建於客戶端的連線
    Socket socket=server.accept();
    //明確資料來源,顯示哪個客戶端Socket連線上了伺服器
    InputStream in=socket.getInputStream();
    File file=new File("D:\\io0512\\server");
    if(!file.exists()){
        file.mkdirs();
    }
    String filename="oracle"+System.currentTimeMillis()+new Random().nextInt(99999)+".java";
    
    //明確目的地
    FileOutputStream fos=new FileOutputStream(file+File.separator+filename);
    //開始複製
    byte[] bytes=new byte[1024];
    int len=0;
    while((len=in.read(bytes))!=-1){
        fos.write(bytes,0,len);
    }
    //回覆客戶端
    OutputStream out=socket.getOutputStream();
    out.write("上傳成功".getBytes());
    
    server.close();//釋放資源
}
}

/*

* 檔案上傳 客戶端

實現步驟:

  1. Socket套接字連線伺服器
  2. 通過Socket獲取位元組輸出流,寫圖片
  3. 使用自己的流物件,讀取圖片資料來源

FileInputStream

  1. 讀取圖片,使用位元組輸出流,將圖片寫到伺服器
  2. 通過Socket套接字獲取位元組輸入流

讀取伺服器發回來的上傳成功

6.關閉資源

*

* public void shutdownOutput() 禁用此Socket的輸出流,間接的相當於告知了伺服器資料寫入完畢

*/

//客戶端TCP
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
    //建立客戶端Socket物件,(指定要連線的伺服器地址與埠號)
    Socket socket=new Socket("127.0.0.1",9999);
    //獲取位元組輸出流,向客戶端傳送資料
    OutputStream out=socket.getOutputStream();
    out.write("你好".getBytes());
        //接收伺服器端的回覆
    //獲取位元組輸入流
    InputStream in=socket.getInputStream();
    byte[] bytes=new byte[1024];
    //把流中的資料儲存到陣列中,並記錄讀取位元組的個數
    int len=in.read(bytes);
    //獲取ip地址
    String ip=socket.getInetAddress().getHostAddress();
    System.out.println("ip為"+ip+"內容"+new String(bytes,0,len));
    
    socket.close();//釋放資源
        
}
}

多執行緒版本

實現伺服器端可以同時接收多個客戶端上傳的檔案。

伺服器端

public class Upload implements Runnable{
    private Socket socket;
    public Upload(Socket socket){
        this.socket=socket;
    }
    
    public void run() {
        
        //明確資料來源,顯示哪個客戶端Socket連線上了伺服器
        InputStream in;
        try {
            in = socket.getInputStream();
            File file=new File("D:\\io0512\\server");
            if(!file.exists()){
                file.mkdirs();
            }
            String filename="oracle"+System.currentTimeMillis()+new Random().nextInt(99999)+".jpg";
            
            //明確目的地
            FileOutputStream fos=new FileOutputStream(file+File.separator+filename);
            //開始複製
            byte[] bytes=new byte[1024];
            int len=0;
            while((len=in.read(bytes))!=-1){
                fos.write(bytes,0,len);
            }
            //回覆客戶端
            OutputStream out=socket.getOutputStream();
            out.write("上傳成功".getBytes());
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
    }

}

客戶端

//客戶端
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
    //建立客戶端物件,明確地址和埠號
    Socket socket=new Socket("192.168.1.151",9999);
    //明確資料來源
    FileInputStream fis=new FileInputStream("D:\\背景\\1.jpg");    
    //明確目的地
    OutputStream out=socket.getOutputStream();//伺服器端
    //開始複製
    int len=0;
    byte[] bytes=new byte[1024];
    while((len=fis.read(bytes))!=-1){
        out.write(bytes,0,len);
    }
    //告知伺服器資料已經沒有了,不讀了
    socket.shutdownOutput();
    //接收伺服器回覆
    InputStream in=socket.getInputStream();
    len=in.read(bytes);
    System.out.println(new String(bytes,0,len));
    
    socket.close();//釋放資源
}
}