31_網路編程(Socket套接字編程)_講義

来源:https://www.cnblogs.com/wanghui1234/archive/2018/09/08/9610710.html
-Advertisement-
Play Games

1、網路三要素及傳輸協議 2、實現UDP協議的發送端和接收端 3、實現TCP協議的客戶端和伺服器 4、TCP上傳文件案例 ...


今日內容介紹
1、網路三要素及傳輸協議
2、實現UDP協議的發送端和接收端
3、實現TCP協議的客戶端和伺服器
4、TCP上傳文件案例

01網路模型

  *A:網路模型
     TCP/IP協議中的四層分別是應用層、傳輸層、網路層和鏈路層,每層分別負責不同的通信功能,接下來針對這四層進行詳細地講解。
       鏈路層:鏈路層是用於定義物理傳輸通道,通常是對某些網路連接設備的驅動協議,例如針對光纖、網線提供的驅動。
       網路層:網路層是整個TCP/IP協議的核心,它主要用於將傳輸的數據進行分組,將分組數據發送到目標電腦或者網路。
       傳輸層:主要使網路程式進行通信,在進行網路通信時,可以採用TCP協議,也可以採用UDP協議。
       應用層:主要負責應用程式的協議,例如HTTP協議、FTP協議等。

02IP地址

 *A:IP地址
      在TCP/IP協議中,這個標識號就是IP地址,它可以唯一標識一臺電腦,
      目前,IP地址廣泛使用的版本是IPv4,它是由4個位元組大小的二進位數來表示,如:00001010000000000000000000000001。
      由於二進位形式表示的IP地址非常不便記憶和處理,因此通常會將IP地址寫成十進位的形式,
      每個位元組用一個十進位數字(0-255)表示,數字間用符號“.”分開,如 “192.168.1.100”
      127.0.0.1 為本地主機地址(本地迴環地址)

03埠號

 *A:埠號
    通過IP地址可以連接到指定電腦,但如果想訪問目標電腦中的某個應用程式,還需要指定埠號。
    在電腦中,不同的應用程式是通過埠號區分的。
    埠號是用兩個位元組(16位的二進位數)表示的,它的取值範圍是0~65535,
    其中,0~1023之間的埠號用於一些知名的網路服務和應用,用戶的普通應用程式需要使用1024以上的埠號,從而避免埠號被另外一個應用或服務所占用

04InetAddress類

  *A:InetAddress類
     /*
      *  表示互聯網中的IP地址
      *    java.net.InetAddress
      *  靜態方法
      *    static InetAddress  getLocalHost()   LocalHost本地主機
      *    返回本地主機,返回值InetAddress對象
      *    
      *    static InetAddress getByName(String hostName)傳遞主機名,獲取IP地址對象
      *    
      *  非靜態方法
      *     String getHoustAddress()獲取主機IP地址
      *     String getHoustName()獲取主機名
      *    
      */
     public class InetAddressDemo {
      public static void main(String[] args)throws UnknownHostException {
        function_1();
      }
      /*
       * static InetAddress getByName(String hostName)傳遞主機名,獲取IP地址對象
       */
      public static void function_1()throws UnknownHostException {
        InetAddress inet = InetAddress.getByName("www.baidu.com");
        System.out.println(inet);
      }
      
      /*
       *  static InetAddress  getLocalHost()   LocalHost本地主機
       */
      public static void function() throws UnknownHostException{
        InetAddress inet = InetAddress.getLocalHost();
        //輸出結果就是主機名,和 IP地址
        System.out.println(inet.toString());
        
        String ip = inet.getHostAddress();
        String name = inet.getHostName();
        System.out.println(ip+"   "+name);
        
        /*String host = inet.toString();
        String[] str = host.split("/");
        for(String s : str){
          System.out.println(s);
        }*/
      }
     }

05UDP協議

   A:UDP協議
     a:UDP協議概述:
      UDP是無連接通信協議,即在數據傳輸時,數據的發送端和接收端不建立邏輯連接。
      簡單來說,當一臺電腦向另外一臺電腦發送數據時,發送端不會確認接收端是否存在,就會發出數據,同樣接收端在收到數據時,也不會向發送端反饋是否收到數據。
     b:UDP協議特點:
      由於使用UDP協議消耗資源小,通信效率高,所以通常都會用於音頻、視頻和普通數據的傳輸例如視頻會議都使用UDP協議,
      因為這種情況即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。

06TCP協議

  *A:TCP協議
    TCP協議是面向連接的通信協議,即在傳輸數據前先在發送端和接收端建立邏輯連接,然後再傳輸數據,它提供了兩台電腦之間可靠無差錯的數據傳輸。
    在TCP連接中必須要明確客戶端與伺服器端,
      由客戶端向服務端發出連接請求,每次連接的創建都需要經過“三次握手”。
      第一次握手,客戶端向伺服器端發出連接請求,等待伺服器確認
      第二次握手,伺服器端向客戶端回送一個響應,通知客戶端收到了連接請求
      第三次握手,客戶端再次向伺服器端發送確認信息,確認連接

07數據包和發送對象介紹

  *A:數據包和發送對象介紹:
    DatagramPacket數據包的作用就如同是“集裝箱”,
       可以將發送端或者接收端的數據封裝起來。然而運輸貨物只有“集裝箱”是不夠的,還需要有碼頭。
       在程式中需要實現通信只有DatagramPacket數據包也同樣不行,為此JDK中提供的一個DatagramSocket類。
       DatagramSocket類的作用就類似於碼頭,使用這個類的實例對象就可以發送和接收DatagramPacket數據包
    DatagramPacket:封裝數據
    DatagramSocket:發送DatagramPacket

08UDP發送端

   *A:UDP發送端
         /*
        *  實現UDP協議的發送端:
        *    實現封裝數據的類 java.net.DatagramPacket  將你的數據包裝
        *    實現數據傳輸的類 java.net.DatagramSocket  將數據包發出去
        *    
        *  實現步驟:
        *    1. 創建DatagramPacket對象,封裝數據, 接收的地址和埠
        *    2. 創建DatagramSocket
        *    3. 調用DatagramSocket類方法send,發送數據包
        *    4. 關閉資源
        *    
        *    DatagramPacket構造方法:
        *      DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
        *      
        *    DatagramSocket構造方法:
        *      DatagramSocket()空參數
        *      方法: send(DatagramPacket d)
        *      
        */
       public class UDPSend {
        public static void main(String[] args) throws IOException{
          //創建數據包對象,封裝要發送的數據,接收端IP,埠
          byte[] date = "你好UDP".getBytes();
          //創建InetAddress對象,封裝自己的IP地址
          InetAddress inet = InetAddress.getByName("127.0.0.1");
          DatagramPacket dp = new DatagramPacket(date, date.length, inet,6000);
          //創建DatagramSocket對象,數據包的發送和接收對象
          DatagramSocket ds = new DatagramSocket();
          //調用ds對象的方法send,發送數據包
          ds.send(dp);
          //關閉資源
          ds.close();
        }
       }

09UDP接收端

   *A:UDP接收端
       /*
        *  實現UDP接收端
        *    實現封裝數據包 java.net.DatagramPacket 將數據接收
        *    實現輸出傳輸     java.net.DatagramSocket 接收數據包
        *    
        *  實現步驟:
        *     1. 創建DatagramSocket對象,綁定埠號
        *         要和發送端埠號一致
        *     2. 創建位元組數組,接收發來的數據
        *     3. 創建數據包對象DatagramPacket
        *     4. 調用DatagramSocket對象方法
        *        receive(DatagramPacket dp)接收數據,數據放在數據包中
        *     5. 拆包
        *          發送的IP地址
        *            數據包對象DatagramPacket方法getAddress()獲取的是發送端的IP地址對象
        *            返回值是InetAddress對象
        *          接收到的位元組個數
        *            數據包對象DatagramPacket方法 getLength()
        *          發送方的埠號
        *            數據包對象DatagramPacket方法 getPort()發送埠
        *     6. 關閉資源
        */
       public class UDPReceive {
        public static void main(String[] args)throws IOException {
          //創建數據包傳輸對象DatagramSocket 綁定埠號
          DatagramSocket ds = new DatagramSocket(6000);
          //創建位元組數組
          byte[] data = new byte[1024];
          //創建數據包對象,傳遞位元組數組
          DatagramPacket dp = new DatagramPacket(data, data.length);
          //調用ds對象的方法receive傳遞數據包
          ds.receive(dp);
          
      
        }
       }

10UDP接收端的拆包

   *A:UDP接收端的拆包 
      
      /*
       *  實現UDP接收端
       *    實現封裝數據包 java.net.DatagramPacket 將數據接收
       *    實現輸出傳輸     java.net.DatagramSocket 接收數據包
       *    
       *  實現步驟:
       *     1. 創建DatagramSocket對象,綁定埠號
       *         要和發送端埠號一致
       *     2. 創建位元組數組,接收發來的數據
       *     3. 創建數據包對象DatagramPacket
       *     4. 調用DatagramSocket對象方法
       *        receive(DatagramPacket dp)接收數據,數據放在數據包中
       *     5. 拆包
       *          發送的IP地址
       *            數據包對象DatagramPacket方法getAddress()獲取的是發送端的IP地址對象
       *            返回值是InetAddress對象
       *          接收到的位元組個數
       *            數據包對象DatagramPacket方法 getLength()
       *          發送方的埠號
       *            數據包對象DatagramPacket方法 getPort()發送埠
       *     6. 關閉資源
       */
      public class UDPReceive {
        public static void main(String[] args)throws IOException {
          //創建數據包傳輸對象DatagramSocket 綁定埠號
          DatagramSocket ds = new DatagramSocket(6000);
          //創建位元組數組
          byte[] data = new byte[1024];
          //創建數據包對象,傳遞位元組數組
          DatagramPacket dp = new DatagramPacket(data, data.length);
          //調用ds對象的方法receive傳遞數據包
          ds.receive(dp);
          
          //獲取發送端的IP地址對象
          String ip=dp.getAddress().getHostAddress();
          
          //獲取發送的埠號
          int port = dp.getPort();
          
          //獲取接收到的位元組個數
          int length = dp.getLength();
          System.out.println(new String(data,0,length)+"..."+ip+":"+port);
          ds.close();
        }
      }

11鍵盤輸入的聊天

   *A:鍵盤輸入的聊天
    *a:發送端:
      /*
       * 實現UDP發送,鍵盤輸入的形式
       * 輸入完畢,發送給接收端      
       */
      public class UDPSend {
        public static void main(String[] args) throws IOException{
          Scanner sc = new Scanner(System.in);
          DatagramSocket ds = new DatagramSocket();
          InetAddress inet = InetAddress.getByName("127.0.0.1");
          while(true){
          String message = sc.nextLine();
          /*if("886".equals(message)){
            break;
          }*/
          byte[] date = message.getBytes();
          DatagramPacket dp = new DatagramPacket(date, date.length, inet,6000);
          ds.send(dp);
          }
        //  ds.close();
        }
      }
       
       

       /*
        *  實現UDP接收端
        *  永不停歇的接收端
        */
       public class UDPReceive {
        public static void main(String[] args)throws IOException {
          //創建數據包傳輸對象DatagramSocket 綁定埠號
          DatagramSocket ds = new DatagramSocket(6000);
          //創建位元組數組
          byte[] data = new byte[1024];
          //創建數據包對象,傳遞位元組數組
          while(true){
          DatagramPacket dp = new DatagramPacket(data, data.length);
          //調用ds對象的方法receive傳遞數據包
          ds.receive(dp);
          
          //獲取發送端的IP地址對象
          String ip=dp.getAddress().getHostAddress();
          
          //獲取發送的埠號
          int port = dp.getPort();
          
          //獲取接收到的位元組個數
          int length = dp.getLength();
          System.out.println(new String(data,0,length)+"..."+ip+":"+port);
          }
          //ds.close();
        }
       }

12TCP的客戶端和伺服器

   *A:TCP的客戶端和伺服器
      TCP通信同UDP通信一樣,都能實現兩台電腦之間的通信,通信的兩端都需要創建socket對象。
      區別在於,UDP中只有發送端和接收端,不區分客戶端與伺服器端,電腦之間可以任意地發送數據。
      而TCP通信是嚴格區分客戶端與伺服器端的,在通信時,必須先由客戶端去連接伺服器端才能實現通信,
      伺服器端不可以主動連接客戶端,並且伺服器端程式需要事先啟動,等待客戶端的連接。
      在JDK中提供了兩個類用於實現TCP程式,一個是ServerSocket類,用於表示伺服器端,一個是Socket類,用於表示客戶端。
      通信時,首先創建代表伺服器端的ServerSocket對象,該對象相當於開啟一個服務,並等待客戶端的連接,然後創建代表客戶端的Socket對象向伺服器端發出連接請求,伺服器端響應請求,兩者建立連接開始通信。

13TCP的客戶端程式

  *A:TCP的客戶端程式
   /*
    *  實現TCP客戶端,連接到伺服器
    *  和伺服器實現數據交換
    *  實現TCP客戶端程式的類 java.net.Socket
    *  
    *  構造方法:
    *      Socket(String host, int port)  傳遞伺服器IP和埠號
    *      註意:構造方法只要運行,就會和伺服器進行連接,連接失敗,拋出異常
    *      
    *    OutputStream  getOutputStream() 返回套接字的輸出流
    *      作用: 將數據輸出,輸出到伺服器
    *      
    *    InputStream getInputStream() 返回套接字的輸入流
    *      作用: 從伺服器端讀取數據
    *      
    *    客戶端伺服器數據交換,必須使用套接字對象Socket中的獲取的IO流,自己new流,不行
    */
   public class TCPClient {
    public static void main(String[] args)throws IOException {
      //創建Socket對象,連接伺服器
      Socket socket = new Socket("127.0.0.1", 8888);
      //通過客戶端的套接字對象Socket方法,獲取位元組輸出流,將數據寫向伺服器
      OutputStream out = socket.getOutputStream();
      out.write("伺服器OK".getBytes());
      
 
      
      socket.close();
    }
   }

14TCP的伺服器程式accept方法

   A:TCP的伺服器程式accept方法
     /*
      *  實現TCP伺服器程式
      *  表示伺服器程式的類 java.net.ServerSocket
      *  構造方法:
      *    ServerSocket(int port) 傳遞埠號
      *  
      *  很重要的事情: 必須要獲得客戶端的套接字對象Socket
      *    Socket  accept()
      */
     public class TCPServer {
      public static void main(String[] args) throws IOException{
        ServerSocket server = new ServerSocket(8888);
        //調用伺服器套接字對象中的方法accept() 獲取客戶端套接字對象
        Socket socket = server.accept();
        //通過客戶端套接字對象,socket獲取位元組輸入流,讀取的是客戶端發送來的數據
        InputStream in = socket.getInputStream();
        byte[] data = new byte[1024];
        int len = in.read(data);
        System.out.println(new String(data,0,len));
      
        
        socket.close();
        server.close();
      }
     }

15TCP的伺服器程式讀取客戶端數據

   A:TCP的伺服器程式讀取客戶端數據
      
      /*
       *  實現TCP客戶端,連接到伺服器
       *  和伺服器實現數據交換
       *  實現TCP客戶端程式的類 java.net.Socket
       *  
       *  構造方法:
       *      Socket(String host, int port)  傳遞伺服器IP和埠號
       *      註意:構造方法只要運行,就會和伺服器進行連接,連接失敗,拋出異常
       *      
       *    OutputStream  getOutputStream() 返回套接字的輸出流
       *      作用: 將數據輸出,輸出到伺服器
       *      
       *    InputStream getInputStream() 返回套接字的輸入流
       *      作用: 從伺服器端讀取數據
       *      
       *    客戶端伺服器數據交換,必須使用套接字對象Socket中的獲取的IO流,自己new流,不行
       */
      public class TCPClient {
        public static void main(String[] args)throws IOException {
          //創建Socket對象,連接伺服器
          Socket socket = new Socket("127.0.0.1", 8888);
          //通過客戶端的套接字對象Socket方法,獲取位元組輸出流,將數據寫向伺服器
          OutputStream out = socket.getOutputStream();
          out.write("伺服器OK".getBytes());
          socket.close();
        }
      }
      /*
       *  實現TCP伺服器程式
       *  表示伺服器程式的類 java.net.ServerSocket
       *  構造方法:
       *    ServerSocket(int port) 傳遞埠號
       *  
       *  很重要的事情: 必須要獲得客戶端的套接字對象Socket
       *    Socket  accept()
       */
      public class TCPServer {
        public static void main(String[] args) throws IOException{
          ServerSocket server = new ServerSocket(8888);
          //調用伺服器套接字對象中的方法accept() 獲取客戶端套接字對象
          Socket socket = server.accept();
          //通過客戶端套接字對象,socket獲取位元組輸入流,讀取的是客戶端發送來的數據
          InputStream in = socket.getInputStream();
          byte[] data = new byte[1024];
          int len = in.read(data);
          System.out.println(new String(data,0,len));
        
        }
      }

16TCP的伺服器和客戶端的數據交換

   A:TCP的伺服器和客戶端的數據交換
      /*
       *  實現TCP客戶端,連接到伺服器
       *  和伺服器實現數據交換
       *  實現TCP客戶端程式的類 java.net.Socket
       *  
       *  構造方法:
       *      Socket(String host, int port)  傳遞伺服器IP和埠號
       *      註意:構造方法只要運行,就會和伺服器進行連接,連接失敗,拋出異常
       *      
       *    OutputStream  getOutputStream() 返回套接字的輸出流
       *      作用: 將數據輸出,輸出到伺服器
       *      
       *    InputStream getInputStream() 返回套接字的輸入流
       *      作用: 從伺服器端讀取數據
       *      
       *    客戶端伺服器數據交換,必須使用套接字對象Socket中的獲取的IO流,自己new流,不行
       */
      public class TCPClient {
        public static void main(String[] args)throws IOException {
          //創建Socket對象,連接伺服器
          Socket socket = new Socket("127.0.0.1", 8888);
          //通過客戶端的套接字對象Socket方法,獲取位元組輸出流,將數據寫向伺服器
          OutputStream out = socket.getOutputStream();
          out.write("伺服器OK".getBytes());
          
          //讀取伺服器發回的數據,使用socket套接字對象中的位元組輸入流
          InputStream in = socket.getInputStream();
          byte[] data = new byte[1024];
          int len = in.read(data);
          System.out.println(new String(data,0,len));
          
          socket.close();
        }
      }
      /*
       *  實現TCP伺服器程式
       *  表示伺服器程式的類 java.net.ServerSocket
       *  構造方法:
       *    ServerSocket(int port) 傳遞埠號
       *  
       *  很重要的事情: 必須要獲得客戶端的套接字對象Socket
       *    Socket  accept()
       */
      public class TCPServer {
        public static void main(String[] args) throws IOException{
          ServerSocket server = new ServerSocket(8888);
          //調用伺服器套接字對象中的方法accept() 獲取客戶端套接字對象
          Socket socket = server.accept();
          //通過客戶端套接字對象,socket獲取位元組輸入流,讀取的是客戶端發送來的數據
          InputStream in = socket.getInputStream();
          byte[] data = new byte[1024];
          int len = in.read(data);
          System.out.println(new String(data,0,len));
          
          //伺服器向客戶端回數據,位元組輸出流,通過客戶端套接字對象獲取位元組輸出流
          OutputStream out = socket.getOutputStream();
          out.write("收到,謝謝".getBytes());
          
          socket.close();
          server.close();
        }
      }
  

17TCP的中的流對象

18TCP圖片上傳案例分析

19TCP上傳客戶端

   *A TCP上傳客戶端
   /*
    *  實現TCP圖片上傳客戶端
    *  實現步驟:
    *    1. Socket套接字連接伺服器
    *    2. 通過Socket獲取位元組輸出流,寫圖片
    *    3. 使用自己的流對象,讀取圖片數據源
    *         FileInputStream
    *    4. 讀取圖片,使用位元組輸出流,將圖片寫到伺服器
    *       採用位元組數組進行緩衝
    *    5. 通過Socket套接字獲取位元組輸入流
    *       讀取伺服器發回來的上傳成功
    *    6. 關閉資源
    */
   public class TCPClient {
    public static void main(String[] args) throws IOException{
      Socket socket = new Socket("127.0.0.1", 8000);
      //獲取位元組輸出流,圖片寫到伺服器
      OutputStream out = socket.getOutputStream();
      //創建位元組輸入流,讀取本機上的數據源圖片
      FileInputStream fis = new FileInputStream("c:\\t.jpg");
      //開始讀寫位元組數組
      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));
      
      fis.close();
      socket.close();
    }
   }

20TCP上傳伺服器

   A:TCP上傳伺服器
   /*
    *  TCP圖片上傳伺服器
    *   1. ServerSocket套接字對象,監聽埠8000
    *   2. 方法accept()獲取客戶端的連接對象
    *   3. 客戶端連接對象獲取位元組輸入流,讀取客戶端發送圖片
    *   4. 創建File對象,綁定上傳文件夾
    *       判斷文件夾存在, 不存,在創建文件夾
    *   5. 創建位元組輸出流,數據目的File對象所在文件夾
    *   6. 位元組流讀取圖片,位元組流將圖片寫入到目的文件夾中
    *   7. 將上傳成功會寫客戶端
    *   8. 關閉資源
    *       
    */
   public class TCPServer {
    public static void main(String[] args) throws IOException{
      ServerSocket server = new ServerSocket(8000);
      Socket socket = server.accept();
      //通過客戶端連接對象,獲取位元組輸入流,讀取客戶端圖片
      InputStream in = socket.getInputStream();
      //將目的文件夾封裝到File對象
      File upload = new File("d:\\upload");
      if(!upload.exists())
        upload.mkdirs();
       
      //創建位元組輸出流,將圖片寫入到目的文件夾中                         
      FileOutputStream fos = new FileOutputStream(upload+"t.jpg");
      //讀寫位元組數組
      byte[] bytes = new byte[1024];
      int len = 0 ;
      while((len = in.read(bytes))!=-1){
        fos.write(bytes, 0, len);
      }
      //通過客戶端連接對象獲取位元組輸出流
      //上傳成功寫回客戶端
      socket.getOutputStream().write("上傳成功".getBytes());
      
      fos.close();
      socket.close();
      server.close();
    }
   }

21TCP圖片上傳問題解決

    /*
     *  實現TCP圖片上傳客戶端
     *  實現步驟:
     *    1. Socket套接字連接伺服器
     *    2. 通過Socket獲取位元組輸出流,寫圖片
     *    3. 使用自己的流對象,讀取圖片數據源
     *         FileInputStream
     *    4. 讀取圖片,使用位元組輸出流,將圖片寫到伺服器
     *       採用位元組數組進行緩衝
     *    5. 通過Socket套接字獲取位元組輸入流
     *       讀取伺服器發回來的上傳成功
     *    6. 關閉資源
     */
    public class TCPClient {
      public static void main(String[] args) throws IOException{
        Socket socket = new Socket("127.0.0.1", 8000);
        //獲取位元組輸出流,圖片寫到伺服器
        OutputStream out = socket.getOutputStream();
        //創建位元組輸入流,讀取本機上的數據源圖片
        FileInputStream fis = new FileInputStream("c:\\t.jpg");
        //開始讀寫位元組數組
        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));
        
        fis.close();
        socket.close();
      }
    }

TCP上傳文件名

  *A:TCP上傳文件名
   /*
    *  TCP圖片上傳伺服器
    *   1. ServerSocket套接字對象,監聽埠8000
    *   2. 方法accept()獲取客戶端的連接對象
    *   3. 客戶端連接對象獲取位元組輸入流,讀取客戶端發送圖片
    *   4. 創建File對象,綁定上傳文件夾
    *       判斷文件夾存在, 不存,在創建文件夾
    *   5. 創建位元組輸出流,數據目的File對象所在文件夾
    *   6. 位元組流讀取圖片,位元組流將圖片寫入到目的文件夾中
    *   7. 將上傳成功會寫客戶端
    *   8. 關閉資源
    *       
    */
   public class TCPServer {
    public static void main(String[] args) throws IOException{
      ServerSocket server = new ServerSocket(8000);
      Socket socket = server.accept();
      //通過客戶端連接對象,獲取位元組輸入流,讀取客戶端圖片
      InputStream in = socket.getInputStream();
      //將目的文件夾封裝到File對象
      File upload = new File("d:\\upload");
      if(!upload.exists())
        upload.mkdirs();
      
      //防止文件同名被覆蓋,從新定義文件名字
      //規則:  功能變數名稱+毫秒值+6位隨機數
      String filename="itcast"+System.currentTimeMillis()+new Random().nextInt(999999)+".jpg";
      //創建位元組輸出流,將圖片寫入到目的文件夾中                         
      FileOutputStream fos = new FileOutputStream(upload+File.separator+filename);
      //讀寫位元組數組
      byte[] bytes = new byte[1024];
      int len = 0 ;
      while((len = in.read(bytes))!=-1){
        fos.write(bytes, 0, len);
      }
      //通過客戶端連接對象獲取位元組輸出流
      //上傳成功寫回客戶端
      socket.getOutputStream().write("上傳成功".getBytes());
      
      fos.close();
      socket.close();
      server.close();
    }
   }

多線程上傳案例

*A:多線程上傳案例
  public class TCPThreadServer {
    public static void main(String[] args) throws IOException {
      ServerSocket server = new ServerSocket(8000);
      while (true) {
        // 獲取到一個客戶端,必須開啟新線程,為這個客戶端服務
        Socket socket = server.accept(); 
        new Thread(new Upload(socket)).start();
      }
    }
  }

  public class Upload implements Runnable {

    private Socket socket;

    public Upload(Socket socket) {
      this.socket = socket;
    }

    public void run() {
      try {
        // 通過客戶端連接對象,獲取位元組輸入流,讀取客戶端圖片
        InputStream in = socket.getInputStream();
        // 將目的文件夾封裝到File對象
        File upload = new File("d:\\upload");
        if (!upload.exists())
          upload.mkdirs();

        // 防止文件同名被覆蓋,從新定義文件名字
        // 規則: 功能變數名稱+毫秒值+6位隨機數
        String filename = "itcast" + System.currentTimeMillis() + new Random().nextInt(999999) + ".jpg";
        // 創建位元組輸出流,將圖片寫入到目的文件夾中
        FileOutputStream fos = new FileOutputStream(upload + File.separator + filename);
        // 讀寫位元組數組
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = in.read(bytes)) != -1) {
          fos.write(bytes, 0, len);
        }
        // 通過客戶端連接對象獲取位元組輸出流
        // 上傳成功寫回客戶端
        socket.getOutputStream().write("上傳成功".getBytes());

        fos.close();
        socket.close();
      } catch (Exception ex) {

      }
    }

  }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.函數的定義 return語句不寫或後邊不加任何對象即為return None 二.函數的參數 無參數 一個參數 多個參數 必須參數 必須按照正確順序和數量傳入參數 關鍵字參數 預設參數 預設參數必須放在必須參數的後面 不定長參數 參數帶一個星號* 參數帶兩個星號** 定義函數的參數時請以必須參數 ...
  • 動態鏈接 要解決空間浪費和更新困難這兩個問題最簡單的辦法就是把程式的模塊相互分割開來,形成獨立的文件,而不再將它們靜態地鏈接在一起。簡單地講,就是不對那些組成程式的目標文件進行鏈接,等到程式要運行時才進行鏈接。也就是說,把鏈接這個過程推遲到了運行時再進行,這就是動態鏈接( Dynamic Linki ...
  • 過期重磅: 全國電腦等級考試二級 Python 語言程式設計考試大綱 (2018 年版) 考試內容 一、Python語言的基本語法元素 二、基本數據類型 三、程式控制結構 四、函數和代碼復用 五、組合數據類型 六、文件和數據格式化 七、Python計算生態 考試方式 上機考試,考試時長 120 分 ...
  • Redis是一個開源(BSD許可),記憶體存儲的數據結構伺服器,可用作資料庫,高速緩存和消息隊列代理。 有時,為了提升整個網站的性能,在開發時會將經常訪問的數據進行緩存,這樣在調用這個數據介面時,可以提高數據載入的效率 本文將在Boot項目中進行Redis的整合,將常用的數據緩存到Redis伺服器中, ...
  • eclipse安裝hibernate tools 下載地址: https://tools.jboss.org/downloads/jbosstools/photon/4.6.0.Final.html 線上安裝 離線安裝 新建java project後加入對應jar包 新建hibernate.cfg. ...
  • 作者作為一個蒟蒻,也是最近才自學了線段樹,不對的地方歡迎大佬們評論,但是不要噴謝謝 好啦,我們就開始說說線段樹吧 線段樹是個支持區間操作和查詢的東東,平時的話還是蠻實用的 下麵以最基本的區間加以及查詢區間和為例 線段樹顧名思義就是棵樹嘛,葉子節點是每個基本點,它們所對應的父親就是它們的和,具體如下圖 ...
  • 題目:消重輸出 題目介紹: 輸入一個正整數,給出消除重覆數字以後最大的整數,註意需要考慮長整數。 例: 輸入:988274320 輸出:9874320 題目分析:這個結果的實現需要兩個步驟:消重和排序。第一步,消重。先用string 和char 將數字分別儲存進char 數組,然後從左邊第一個字元開 ...
  • 想做自己的微博自媒體,微博大v,剛開始我們肯定要有粉絲才可以,但是我們上哪裡去找粉絲那?花錢買,都是僵屍粉,也就是湊湊數而已,所以我們需要加入互粉群,一個群大概1000人,我們每天關註的人上限大概500個,我們總不能一個一個點進去關註吧,好累的,所以我要批量關註,市面上很多批量關註的軟體不太敢用還是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...