<u id="1k2el"></u>
<u id="1k2el"></u>

      咨詢電話:0551-62903161

      學(xué)術(shù)交流

      首頁>官網(wǎng)首頁 > 教育教學(xué) > 學(xué)術(shù)交流 >
      大牛老師教你:java socket模擬http客戶端
      作者:未知  時間:2018-12-29 17:01
       socket是網(wǎng)絡(luò)之間節(jié)點通信的關(guān)鍵技術(shù),關(guān)鍵是三部分
         IP地址、協(xié)議、端口號
      TCP/IP協(xié)議:
         是目前世界上應(yīng)用最為廣泛的協(xié)議,是以TCP和IP為基礎(chǔ)的不同層次上多個協(xié)議的集合,也成TCP/IP協(xié)議族、或TCP/IP協(xié)議棧
                  TCP:Transmission Control Protocol 傳輸控制協(xié)議
                  IP:Internet Protocol 互聯(lián)網(wǎng)協(xié)議
             3、TCP/IP五層模型
                  應(yīng)用層:HTTP、FTP、SMTP、Telnet等
                  傳輸層:TCP/IP
                  網(wǎng)絡(luò)層:
                  數(shù)據(jù)鏈路層:
                  物理層:網(wǎng)線、雙絞線、網(wǎng)卡等
      下面的例子是模擬http請求,也就是桌面瀏覽器的基本功能,可以作為爬蟲功能的基礎(chǔ)


      import java.io.IOException;
      import java.io.InputStream;
      import java.io.OutputStreamWriter;
      import java.net.InetAddress;
      import java.net.Socket;
      import java.net.UnknownHostException;
      import java.util.ArrayList;

      /**
       * 一個簡單的HTTP客戶端,發(fā)送HTTP請求,模擬瀏覽器 可打印服務(wù)器發(fā)送過來的HTTP消息
       
       */
      public class HttpClient {
          private static String encoding = "UTF-8";

          public static void main(String[] args) {
              try {
              //訪問本機,如果訪問其他服務(wù)器,要改成其ip或者域名,其端口大部分是http協(xié)議的默認(rèn)端口80。留意兩點,一是很多服務(wù)器的協(xié)議是https(加密的http協(xié)議),訪問方式不同;二是很多服務(wù)器有禁止爬蟲功能,會返回錯誤信息。    
                  Socket s = new Socket("localhost", 8080);
                  OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
                  StringBuffer sb = new StringBuffer();
                  sb.append("GET /slsint_gd/reportview/reportViewList.jsp HTTP/1.1 ");
                  sb.append("Host: localhost:8088 ");
                  sb.append("Connection: Keep-Alive ");
                  // 注,這是關(guān)鍵的關(guān)鍵,這里一定要一個回車換行,表示消息頭完,不然服務(wù)器會等待
                  sb.append(" ");
                  osw.write(sb.toString());
                  osw.flush();

                  // --輸出服務(wù)器傳回的消息的頭信息
                  InputStream is = s.getInputStream();
                  String line = null;
                  int contentLength = 0;// 服務(wù)器發(fā)送回來的消息長度
                  // 讀取所有服務(wù)器發(fā)送過來的請求參數(shù)頭部信息
                  do {
                      line = readLine(is, 0);
                      // 如果有Content-Length消息頭時取出
                      if (line.startsWith("Content-Length")) {
                          contentLength = Integer.parseInt(line.split(":")[1].trim());
                      }
                      // 打印請求部信息
                      System.out.print(line);
                      // 如果遇到了一個單獨的回車換行,則表示請求頭結(jié)束
                  } while (!line.equals(" "));

                  // --輸消息的體
                  System.out.print(readLine(is, contentLength));

                  // 關(guān)閉流
                  is.close();

              } catch (UnknownHostException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }

          /*
           * 這里我們自己模擬讀取一行,因為如果使用API中的BufferedReader時,它是讀取到一個回車換行后
           * 才返回,否則如果沒有讀取,則一直阻塞,直接服務(wù)器超時自動關(guān)閉為止,如果此時還使用BufferedReader
           * 來讀時,因為讀到最后一行時,最后一行后不會有回車換行符,所以就會等待。如果使用服務(wù)器發(fā)送回來的
           * 消息頭里的Content-Length來截取消息體,這樣就不會阻塞
           *
           * contentLe 參數(shù) 如果為0時,表示讀頭,讀時我們還是一行一行的返回;如果不為0,表示讀消息體,
           * 時我們根據(jù)消息體的長度來讀完消息體后,客戶端自動關(guān)閉流,這樣不用先到服務(wù)器超時來關(guān)閉。
           */
          private static String readLine(InputStream is, int contentLe) throws IOException {
              ArrayList lineByteList = new ArrayList();
              byte readByte;
              int total = 0;
              if (contentLe != 0) {
                  do {
                      readByte = (byte) is.read();
                      lineByteList.add(Byte.valueOf(readByte));
                      total++;
                  } while (total < contentLe);// 消息體讀還未讀完
              } else {
                  do {
                      readByte = (byte) is.read();
                      lineByteList.add(Byte.valueOf(readByte));
                  } while (readByte != 10);
              }

              byte[] tmpByteArr = new byte[lineByteList.size()];
              for (int i = 0; i < lineByteList.size(); i++) {
                  tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
              }
              lineByteList.clear();

              return new String(tmpByteArr, encoding);
          }
      }

      下圖是一個公網(wǎng)網(wǎng)站的結(jié)果,返回了錯誤信息,禁止爬蟲的結(jié)果

       

      友情鏈接:北大青鳥科海學(xué)院合肥濱湖職業(yè)技術(shù)學(xué)院合肥公交技校 安徽衛(wèi)生健康職業(yè)學(xué)院
      獲獎信息:

      地鐵:乘地鐵1號線到合工大南區(qū)B出口,向南800米即到。

      聯(lián)系我們:招生老師15056993965(微信手機同號) ? ? ?0551-62903161

      地址:合肥市包河區(qū)馬鞍山路富成大廈4樓北大青鳥(合工大東門斜對面)

      日韩黄色毛片在线观看_96精品人妻大胆无码_亚洲一区二区在线波多野_在线视频一区二区三期
      <u id="1k2el"></u>
      <u id="1k2el"></u>

          一本久久a久久精品不卡 | 亚洲国内自拍中文 | 一级做a爱免费视频在线观看 | 亚洲色婷婷爱婷婷综合精品 | 制服丝袜欧美中文字幕在线 | 亚洲精品国产一卡二卡三 |