TCP通信(單線程多線程)


    TCP通信

在JDK中提供了兩個類用於實現TCP程序,一個是ServerSocket類,用於表示服務器端,一個是Socket類,用於表示客戶端。

通信時,首先創建代表服務器端的ServerSocket對象,該對象相當於開啟一個服務,並等待客戶端的連接,然后創建代表客戶端的Socket對象向服務器端發出連接請求,服務器端響應請求,兩者建立連接開始通信。

      ServerSocket類(服務器端)

 

 方法

 

 

ServerSocket對象負責監聽某台計算機的某個端口號,在創建ServerSocket對象后,需要繼續調用該對象的accept()方法,接收來自客戶端的請求。當執行了accept()方法之后,服務器端程序會發生阻塞,直到客戶端發出連接請求,accept()方法才會返回一個Scoket對象用於和客戶端實現通信,程序才能繼續向下執行。

//服務器對象
    ServerSocket server=new ServerSocket(9999);
    //和客戶端創建連接,
    Socket socket=server.accept();

 

      Socket類(客戶端)

ServerSocket對象可以實現服務端程序,但只實現服務器端程序還不能完成通信,此時還需要一個客戶端程序與之交互,為此JDK提供了一個Socket類,用於實現TCP客戶端程序。

 

 

 

 

 Socket的常用方法

 

 

                                                                                          於向服務器端發送數據

在Socket類的常用方法中,getInputStream()和getOutStream()方法分別用於獲取輸入流和輸出流。當客戶端和服務端建立連接后,數據是以IO流的形式進行交互的,從而實現通信。

 

 

 

  實現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 Demo01 {
public static void main(String[] args) throws IOException {
    //創建服務器對象
    ServerSocket server=new ServerSocket(9999);
    while(true){
        Socket socket=server.accept();
        //啟動線程,完成與當前客戶端的數據交互過程
        new Thread(new Upload(socket)).start();//創建線程任務
    }
    
    
}
}

客戶端

//客戶端
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();//釋放資源
}
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM