程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java應用Socket類吸收和發送數據

java應用Socket類吸收和發送數據

編輯:關於JAVA

java應用Socket類吸收和發送數據。本站提示廣大學習愛好者:(java應用Socket類吸收和發送數據)文章只能為提供參考,不一定能成為您想要的結果。以下是java應用Socket類吸收和發送數據正文


收集運用分為客戶端和辦事端兩部門,而Socket類是擔任處置客戶端通訊的Java類。經由過程這個類可以銜接到指定IP或域名的辦事器上,而且可以和辦事器相互發送和接收數據。在本文及前面的數篇文章中將具體評論辯論Socket類的應用,內容包含Socket類基本、林林總總的銜接方法、get和set辦法、銜接進程中的超時和封閉收集銜接等。

在本文中,我們將評論辯論應用Socket類的根本步調和辦法。普通收集客戶端法式在銜接辦事法式時要停止以下三步操作。

  1. 銜接辦事器
  2. 發送和吸收數據
  3. 封閉收集銜接
  4. 1、銜接辦事器

    在客戶端可以經由過程兩種方法來銜接辦事器,一種是經由過程IP的方法來銜接辦事器,而別的一種是經由過程域名方法來銜接辦事器。

    其實這兩種方法從實質下去看是一種方法。在底層客戶端都是經由過程IP來銜接辦事器的,但這兩種方法有必定的差別,假如經由過程IP方法來銜接辦事端法式,客戶端只簡略地依據IP停止銜接,假如經由過程域名來銜接辦事器,客戶端必需經由過程DNS將域名解析成IP,然後再依據這個IP來停止銜接。

    在許多法式設計說話或開辟對象中(如C/C++、Delphi)應用域名方法銜接辦事器時必需本身先將域名解析成IP,然後再經由過程IP停止銜接,而在Java中曾經將域名解析功效包括在了Socket類中,是以,我們只需象應用IP一樣應用域名便可。

    經由過程Socket類銜接辦事器法式最經常使用的辦法就是經由過程Socket類的結構函數將IP或域名和端標語作為參數傳入Socket類中。Socket類的結構函數有許多重載情勢,在這一節只評論辯論個中最經常使用的一種情勢:public Socket(String host, int port)。從這個結構函數的界說來看,只須要將IP或域名和端標語直接傳入結構函數便可。上面的代碼是一個銜接辦事端法式的例子法式:

    package mysocket; 
    import java.net.*; 
    public class MyConnection
    {
      public static void main(String[] args)
      {
        try
        {
          if (args.length > 0)
          {
            Socket socket = new Socket(args[0], 80);
            System.out.println(args[0] + "已銜接勝利!");
          }
          else
            System.out.println("請指定IP或域名!");
        }
        catch (Exception e)
        {
          System.err.println("毛病信息:" + e.getMessage());
        }
      }
    }
    

    在下面的中,經由過程敕令行參數將IP或域名傳入法式,然後經由過程Socket socket = new Socket(args[0], 80)銜接經由過程敕令行參數所指定的IP或域名的80端口。因為Socket類的結構函數在界說時應用了throws,是以,在挪用Socket類的結構函數時,必需應用try…catch語句來捕獲毛病,或許對main函數應用throws語句來拋失足誤。

    應用Socket類銜接辦事器可以斷定一台主機有哪些端口被翻開。上面的代碼是一個掃描本機有哪些端口被翻開的法式。

    2、發送和吸收數據

    在Socket類中最主要的兩個辦法就是getInputStream和getOutputStream。這兩個辦法分離用來獲得用於讀取和寫入數據的InputStream和OutputStream對象。在這裡的InputStream讀取的是辦事器法式向客戶端發送過去的數據,而OutputStream是客戶端要向辦事端法式發送的數據。

    在編寫現實的收集客戶端法式時,是應用getInputStream,照樣應用getOutputStream,和先應用誰後應用誰由詳細的運用決議。如經由過程銜接郵電出書社網站(www.ptpress.com.cn)的80端口(普通為HTTP協定所應用的默許端口),而且發送一個字符串,最初再讀取從www.ptpress.com.cn前往的信息。

    package mysocket;
    import java.net.*;
    import java.io.*; 
    public class MyConnection2
    {
      public static void main(String[] args) throws Exception
      {
        Socket socket = new Socket("www.ptpress.com.cn", 80);
        // 向辦事端法式發送數據
        OutputStream ops = socket.getOutputStream();    
        OutputStreamWriter opsw = new OutputStreamWriter(ops);
        BufferedWriter bw = new BufferedWriter(opsw);
         
        bw.write("hello world\r\n\r\n");
        bw.flush();
         
        // 從辦事端法式吸收數據
        InputStream ips = socket.getInputStream();
        InputStreamReader ipsr = new InputStreamReader(ips);
        BufferedReader br = new BufferedReader(ipsr);
        String s = "";    
        while((s = br.readLine()) != null)
          System.out.println(s);    
        socket.close();
      }
    }
    

    在編寫下面代碼時要留意以下兩點:

    1. 為了進步數據傳輸的效力,Socket類並沒有在每次挪用write辦法後都停止數據傳輸,而是將這些要傳輸的數據寫到一個緩沖區裡(默許是8192個字節),然後經由過程flush辦法將這個緩沖區裡的數據一路發送出去,是以,bw.flush();是必需的。

    2. 在發送字符串時之所以在Hello World後加上 “\r\n\r\n”,這是由於HTTP協定頭是以“\r\n\r\n”作為停止標記(HTTP協定的具體內容將在今後講授),是以,經由過程在發送字符串後參加“\r\n\r\n”,可使辦事端法式以為HTTP頭曾經停止,可以處置了。假如不加“\r\n\r\n”,那末辦事端法式將一向期待HTTP頭的停止,也就是“\r\n\r\n”。假如是如許,辦事端法式就不會向客戶端發送呼應信息,而br.readLine()將因沒法讀以呼應信息面被壅塞,直到銜接超時。

    3、封閉收集銜接

    到如今為止,我們對Socket類的根本應用辦法曾經有了初步的懂得,但在Socket類處置完數據後,最公道的掃尾辦法是應用Socket類的close辦法封閉收集銜接。固然在中曾經應用了close辦法,但使收集銜接封閉的辦法不只僅只要close辦法,上面就讓我們看看Java在甚麼情形下可使收集銜接封閉。

    可以惹起收集銜接封閉的情形有以下4種:

    1.  直接挪用Socket類的close辦法。
    2.  只需Socket類的InputStream和OutputStream有一個封閉,收集銜接主動封閉(必需經由過程挪用InputStream和OutputStream的close辦法封閉流,能力使收集心愛接主動封閉)。
    3. 在法式加入時收集銜接主動封閉。
    4. 將Socket對象設為null或未封閉最讓用new Socket(…)樹立新對象後,由JVM的渣滓收受接管器收受接管為Socket對象分派的內存空間後主動封閉收集銜接。  
    5. 固然這4種辦法都可以到達異樣的目標,但一個硬朗的收集法式最好應用第1種或第2種辦法封閉收集銜接。這是由於第3種和第4種辦法普通其實不會立時封閉收集銜接,假如是如許的話,關於某些運用法式,將會遺留年夜量無用的收集銜接,這些收集銜接會占用年夜量的體系資本。

      在Socket對象被封閉後,我們可以經由過程isClosed辦法來斷定某個Socket對象能否處於封閉狀況。但是應用isClosed辦法所前往的只是Socket對象確當前狀況,也就是說,不論Socket對象能否已經銜接勝利過,只需處於封閉狀況,isClosde就前往true。假如只是樹立一個未銜接的Socket對象,isClose也異樣前往true。以下面的代碼將輸入false。

      Socket socket = new Socket();
      System.out.println(socket.isClosed());

      除isClose辦法,Socket類還有一個isConnected辦法來斷定Socket對象能否銜接勝利。看到這個名字,或許讀者會發生誤會。其實isConnected辦法所斷定的其實不是Socket對象確當前銜接狀況,而是Socket對象能否已經銜接勝利過,假如勝利銜接過,即便如今isClose前往true,isConnected依然前往true。是以,要斷定以後的Socket對象能否處於銜接狀況,必需同時應用isClose和isConnected辦法,即只要當isClose前往false,isConnected前往true的時刻Socket對象才處於銜接狀況。上面的代碼演示了上述Socket對象的各類狀況的發生進程。

      package mysocket;
      import java.net.*; 
      public class MyCloseConnection
      {
        public static void printState(Socket socket, String name)
        {
          System.out.println(name + ".isClosed():" + socket.isClosed());
          System.out.println(name + ".isConnected():" + socket.isConnected());
          if (socket.isClosed() == false && socket.isConnected() == true)
            System.out.println(name + "處於銜接狀況!");
          else
            System.out.println(name + "處於非銜接狀況!");
          System.out.println();
        }
        public static void main(String[] args) throws Exception
        {
          Socket socket1 = null, socket2 = null;
       
          socket1 = new Socket("www.ptpress.com.cn", 80);
          printState(socket1, "socket1");
       
          socket1.getOutputStream().close();
          printState(socket1, "socket1");
       
          socket2 = new Socket();
          printState(socket2, "socket2");
       
          socket2.close();
          printState(socket2, "socket2");
        }
      }
      

      運轉下面的代碼後,將有以下的輸入成果:

      socket1.isClosed():false
      socket1.isConnected():true
      socket1處於銜接狀況!
      socket1.isClosed():true
      socket1.isConnected():true
      socket1處於非銜接狀況!
      socket2.isClosed():false
      socket2.isConnected():false
      socket2處於非銜接狀況!
      socket2.isClosed():true
      socket2.isConnected():false
      socket2處於非銜接狀況!

      從輸入成果可以看出,在socket1的OutputStream封閉後,socket1也主動封閉了。而在下面的代碼我們可以看出,關於一個並未銜接到辦事真個Socket對象socket2,它的isClosed辦法為false,而要想讓socket2的isClosed辦法前往true,必需應用socket2.close顯示地挪用close辦法。

      固然在年夜多半的時刻可以直接應用Socket類或輸出輸入流的close辦法封閉收集銜接,但有時我們只願望封閉OutputStream或InputStream,而在封閉輸出輸入流的同時,其實不封閉收集銜接。這就須要用到Socket類的別的兩個辦法:shutdownInput和shutdownOutput,這兩個辦法只封閉響應的輸出、輸入流,而它們並沒有同時封閉收集銜接的功效。和isClosed、isConnected辦法一樣,Socket類也供給了兩個辦法來斷定Socket對象的輸出、輸入流能否被封閉,這兩個辦法是isInputShutdown()和isOutputShutdown()。上面的代碼演示了只封閉輸出、輸入流的進程:

      package mysocket;
      import java.net.*; 
      public class MyCloseConnection1
      {
        public static void printState(Socket socket)
        {
          System.out.println("isInputShutdown:" + socket.isInputShutdown());
          System.out.println("isOutputShutdown:" + socket.isOutputShutdown());
          System.out.println("isClosed:" + socket.isClosed());
          System.out.println();
        }
        public static void main(String[] args) throws Exception
        {
          Socket socket = new Socket("www.ptpress.com.cn", 80);
          printState(socket);
          socket.shutdownInput();
          printState(socket);
          socket.shutdownOutput();
          printState(socket);
        }
      }
      

      在運轉下面的代後,將獲得以下的輸入成果:

      isInputShutdown:false
      isOutputShutdown:false
      isClosed:false
      isInputShutdown:true
      isOutputShutdown:false
      isClosed:false
      isInputShutdown:true
      isOutputShutdown:true
      isClosed:false

      從輸入成果可以看出,isClosed辦法一向前往false,是以,可以確定,shutdownInput和shutdownOutput其實不影響Socket對象的狀況。

      願望本文所述對你有所贊助,java應用Socket類吸收和發送數據內容就給年夜家引見到這裡了。願望年夜家持續存眷我們的網站!想要進修java可以持續存眷本站。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved