java中講講URL的用法

URL類(lèi)的實(shí)例
馬克-to-win:URL(Uniform Resource Locator-----一致資源查找器)它用來(lái)指向Internet上的資源文件,比如 http://java.sun.com:8080/docs/introdiction.htm net包中的URL類(lèi)提供API來(lái)訪問(wèn)Internet上的信息。
比如以上的URL中:馬克- to-win:馬克 java社區(qū):防盜版實(shí)名手機(jī)尾號(hào): 73203。
1)協(xié)議:http
2)IP 地址或主機(jī)名:java.sun.com
3)端口號(hào):8080
4)實(shí)際文件路徑:docs/introdiction.htm



例:2.4.1
/*no need to have network through to run the program.*/
import java.net.*;
import java.io.*;
public class TestMark_to_win {
    public static void main(String[] args) throws Exception {
        /* Class URL represents a Uniform Resource Locator, a pointer to a
         * "resource" on the World Wide Web. A resource can be something as
         * simple as a file or a directory, public URL(String spec)throws
         * MalformedURLException: Creates a URL object from the String
         * representation.
         */
        URL aURL = new URL("http://java.sun.com:8080/docs/books/"
                + "tutorial/index.html");
        System.out.println("protocol = " + aURL.getProtocol());
        System.out.println("host = " + aURL.getHost());
        System.out.println("filename = " + aURL.getFile());
        System.out.println("default port = " + aURL.getDefaultPort());
        System.out.println("port = " + aURL.getPort());
    }
}

輸出結(jié)果:

protocol = http
host = java.sun.com
filename = /docs/books/tutorial/index.html
default port = 80
port = 8080




例:2.4.2

/* This program needs an open connection to run.
*/
import java.net.*;
import java.io.*;
import java.util.*;
public class TestMark_to_win {
    public static void main(String[] args) throws Exception {
        URL yahoo = new URL("https://www.oracle.com/index.html");
        /* public URLConnection openConnection() throws IOException: Returns a
         * URLConnection object that represents a connection to the remote
         * object referred to by the URL.
         */
        URLConnection yahooConnection = yahoo.openConnection();
        /* public long getLastModified() Returns the value of the last-modified
         * header field. The result is the number of milliseconds since January
         * 1, 1970 GMT.
         */
        System.out.println("content LastModified"
                + new Date(yahooConnection.getLastModified()));
        /*public InputStream getInputStream()throws IOException: Returns an
         * input stream that reads from this open connection.
         */
        // DataInputStream in = new
        // DataInputStream(yahooConnection.getInputStream());
        BufferedReader in = new BufferedReader(new InputStreamReader(
                yahooConnection.getInputStream()));
        String inputLine;
        for (int i = 0; i < 25; i++) {
            inputLine = in.readLine();
            System.out.println(inputLine);
        }
        in.close();
    }
}

輸出結(jié)果:

content LastModifiedTue Mar 27 06:23:25 CST 2018


<!DOCTYPE html>

<html lang="en-US" class="no-js">

<!-- BEGIN:  Compass/HomePage3 -->

<!--  BEGIN:  Compass/HomePage3/Head-HTML -->

<head>

    <title>Oracle | Integrated Cloud Applications and Platform Services</title>
    <meta name="Title" content="Oracle | Integrated Cloud Applications and Platform Services">
  
        <meta name="Description" content="Oracle offers a comprehensive and fully integrated stack of cloud applications and platform services.">
  
    <meta name="Keywords" content="enterprise, applications, software, database, middleware, fusions, business, hardware, Oracle">  
  
  
    <meta name="robots" content="index, follow">






后序及提高:
 
我們先給大家普及一下同步和異步的概念。 引自百度百科:同步指兩個(gè)或兩個(gè)以上隨時(shí)間變化的量在變化過(guò)程中保持一定的相對(duì)關(guān)系。
同步(英語(yǔ):Synchronization),指對(duì)在一個(gè)系統(tǒng)中所發(fā)生的事件(event)之間進(jìn)行協(xié)調(diào),在時(shí)間上出現(xiàn)一致性與統(tǒng)一化的現(xiàn)象。例如,你想將32軌的音頻信號(hào)錄制在兩臺(tái)16軌磁帶機(jī)上,則這兩個(gè)磁帶機(jī)的磁帶傳送軸就需要鎖定在一起,這個(gè)過(guò)程就稱(chēng)為同步。如果這兩個(gè)設(shè)備沒(méi)有進(jìn)行同步,無(wú)論它們開(kāi)始的時(shí)間多么一致,也會(huì)由于兩臺(tái)設(shè)備機(jī)械結(jié)構(gòu)的差異而產(chǎn)生時(shí)間漂移 。


異步是指用戶(hù)程序執(zhí)行IO操作后便開(kāi)始做自己的事情,當(dāng)IO操作已經(jīng)完成的時(shí)候,會(huì)得到IO完成的通知。用戶(hù)程序再接著干。一點(diǎn)兒事兒都不耽誤。

心跳,長(zhǎng)連接,短連接的關(guān)系: 連接建立后,如果不斷開(kāi)連接,缺省就是“長(zhǎng)連接”,不需要發(fā)送數(shù)據(jù)來(lái)保持連接。但網(wǎng)上總說(shuō)要發(fā)“心跳”來(lái)維持長(zhǎng)連接?為什么?因?yàn)橛行┍O(jiān)聽(tīng)所有端口的防火墻或者電腦管理軟件會(huì)把超過(guò)一定時(shí)間沒(méi)有數(shù)據(jù)傳輸?shù)倪B接當(dāng)作死連接,這些軟件會(huì)自動(dòng)將死連接斷開(kāi)。當(dāng)有心跳時(shí),不會(huì)被這類(lèi)軟件當(dāng)做死連接。短連接表示當(dāng)需要與目標(biāo)通信時(shí)創(chuàng)建連接,通訊一結(jié)束立刻斷開(kāi)。

TCP設(shè)計(jì)內(nèi)部包含了心跳信號(hào)。 但是這個(gè)心跳信號(hào)和平臺(tái)相關(guān),且默認(rèn)關(guān)閉。我們盡量不要依賴(lài)這個(gè)功能。

udp用于傳輸視頻流,音頻流或傳感器流等,少傳數(shù)據(jù)沒(méi)事。大不了花屏,沙沙聲等。如需確認(rèn)對(duì)方還在線(xiàn),則也需心跳。有時(shí)在你的手機(jī)上可以設(shè)置一個(gè)指示燈,如對(duì)方在線(xiàn),可讓等亮著,如不在線(xiàn)了,可讓燈滅著。比如有時(shí)心情不好,即使在線(xiàn),也不說(shuō)話(huà)。所以沒(méi)數(shù)據(jù),但有心跳。

bio,nio和AIO區(qū)別:
馬克-to-win:我們這章講的io,實(shí)際上是bio,即blocked io(阻塞式io)。sun公司推出bio以后,用戶(hù)馬上就反應(yīng),這種bio在多用戶(hù)時(shí)效率比較低。sun公司在1.4版本馬上推出了nio,所謂的new io和后來(lái)的AIO(異步IO)。

AIO異步非阻塞IO:
   在此種模式下,用戶(hù)進(jìn)程只需要發(fā)起一個(gè)IO操作然后立即返回,等IO操作真正的完成 以后,應(yīng)用程序會(huì)得到IO操作完成的通知,此時(shí)用戶(hù)進(jìn)程只需要對(duì)數(shù)據(jù)進(jìn)行處理就好了,因?yàn)檎嬲腎O讀取或者寫(xiě)入操作已經(jīng)由 內(nèi)核完成了。

這么看貌似異步應(yīng)該比同步的效率高,但是實(shí)際性能測(cè)下來(lái),并不一定是這樣。因?yàn)楫惒揭胪瓿?,需要一些額外的線(xiàn)程去工作,這一定會(huì)花費(fèi)額外的資源。

馬克-to-win:后來(lái)在實(shí)際的工作當(dāng)中,人們發(fā)現(xiàn)nio好是好,但使用起來(lái)非常困難。有的工程師花了半年以上的時(shí)間,終于把自己的nio系統(tǒng)磨合的非常精湛了。突然發(fā)覺(jué)java界又出了一個(gè)新的東西,叫做netty。就是有人覺(jué)得nio不好使,把他封裝成了一個(gè)新技術(shù)叫netty。那些使用nio的工程師大呼太坑人了。后來(lái)很多人就轉(zhuǎn)向了netty。使了一段時(shí)間,發(fā)覺(jué)業(yè)內(nèi)又出了一個(gè)新的東西叫vert.x。這個(gè)技術(shù)是又把netty封裝了一下。里面還有一些aio的東西。這就是java行業(yè)狀況。更新?lián)Q代非常快?!?br>
我們的策略是把bio學(xué)好,基礎(chǔ)打牢,之后什么在當(dāng)時(shí)找工作時(shí)流行學(xué)什么。這就是我的前沿課程有幾十門(mén)的原因。




作業(yè):
1) 查找某個(gè)www.microsoft.com的IP地址。
2)檢查http://www.microsoft.com:8080/docs/books/屬性。
3)把www.263.com的內(nèi)容前三行存在一個(gè)文件中。
4)用Socket和datagram, 同時(shí)實(shí)現(xiàn)密碼驗(yàn)證。

課外作業(yè):
5)醫(yī)院系統(tǒng):肚子疼可能是什麼???感冒?結(jié)石?(在服務(wù)器端有一文件存著這些信息)
6)請(qǐng)做一個(gè)Web服務(wù)器,客戶(hù)端能打印出一個(gè)html文件。

大作業(yè):
編寫(xiě)仿安卓的網(wǎng)絡(luò)異步回調(diào)底層實(shí)現(xiàn)代碼(AsynNetUtils和handler等),思路:網(wǎng)上有很多異步回調(diào)代碼,但都是在同一臺(tái)機(jī)器上,找不到在不同機(jī)器之間如何異步回調(diào)?這里提供一個(gè)思路,客戶(hù)端在主線(xiàn)程發(fā)送完消息以后,(啟動(dòng)一額外線(xiàn)程去監(jiān)聽(tīng)端口動(dòng)向,當(dāng)有數(shù)據(jù)進(jìn)來(lái)時(shí),就回調(diào)自己的某一方法即可)同時(shí)主線(xiàn)繼續(xù)該干什么干什么。編寫(xiě)時(shí)可參考我參考目錄下的網(wǎng)頁(yè)。

項(xiàng)目一:
做一個(gè)類(lèi)似百度后端爬蟲(chóng)的程序。
在bat3 家巨頭公司中,騰訊和阿里的程序的理念并不難理解,阿里主要是電子商務(wù)網(wǎng)站,我們?cè)诤竺娴木W(wǎng)站學(xué)習(xí)當(dāng)中,可以模仿制作類(lèi)似這樣的項(xiàng)目。騰訊的聊天兒程序我們可以在后面的課外閱讀當(dāng)中看到。最后只剩下百度的后臺(tái)爬蟲(chóng)程序,貌似比較難做。我們這個(gè)項(xiàng)目的目標(biāo)就是做這件事。爬蟲(chóng)的原理是這樣的,給定一個(gè)網(wǎng)頁(yè),我們通過(guò)解析,發(fā)現(xiàn)里面有五個(gè)url,先把這五個(gè)url放在未完成url隊(duì)列里,我們可以按照寬度搜索的算法,把第一個(gè)url網(wǎng)頁(yè)下載下來(lái),把他里面的六個(gè) url再放在未完成url隊(duì)列里,處理過(guò)的url放在數(shù)據(jù)庫(kù)中,把那個(gè)url的標(biāo)題和關(guān)鍵字甚至內(nèi)容也都存下來(lái)。當(dāng)用戶(hù)在瀏覽器中輸入關(guān)鍵字時(shí),你就在數(shù)據(jù)庫(kù)中找到符合關(guān)鍵字的url,把它返回回來(lái),當(dāng)用戶(hù)點(diǎn)擊你的url時(shí),用戶(hù)就可以進(jìn)入網(wǎng)頁(yè)了。




項(xiàng)目2:
做一個(gè)類(lèi)似于tomcat的服務(wù)器。在客戶(hù)端的窗口里敲入192.168.1.4:8888/servlet1 mark就能執(zhí)行另外一臺(tái)機(jī)器上,我們監(jiān)聽(tīng)8888端口的服務(wù)器程序,它會(huì)用反射方法執(zhí)行bin目錄下的servlet1的doGet方法接受mark作為輸入?yún)?shù),且返回hello mark作為返回值返回到客戶(hù)端機(jī)器上。
拓展思考,如果輸入?yún)?shù)是一段代碼的話(huà),你的doGet方法,完全可以上一章的發(fā)明自己語(yǔ)言一樣,把代碼寫(xiě)入到一個(gè)文件當(dāng)中,運(yùn)行它,這就是后門(mén)的原理。我們的課程不討論后門(mén)的制作,但通過(guò)我上面對(duì)后門(mén)原理的提及,我們重點(diǎn)要講的是對(duì)后門(mén)的防范。如果你的公司把程序外包出去,外包程序員設(shè)計(jì)一個(gè)后門(mén),他緊接著可以再制作一段木馬,于是就可以肆意妄為了。對(duì)后門(mén)的防范,比如他可以在doGet當(dāng)中,加上一個(gè)參數(shù)判斷,比如當(dāng)有mark這個(gè)參數(shù)值時(shí),才運(yùn)行他那個(gè)后門(mén)程序。正常的誰(shuí)也不會(huì)用這個(gè)參數(shù)。360等防病毒軟件,也會(huì)認(rèn)為你這個(gè)程序,就是正常的用戶(hù)邏輯,也查不出來(lái)。所以最后的結(jié)論是,如果想防后門(mén),唯有進(jìn)行源代碼級(jí)別行行篩查。才能徹底杜絕后門(mén)。接著咱們講木馬。最新的木馬完全可以用純javascript編寫(xiě)。javascript完全正規(guī)的放在網(wǎng)頁(yè)當(dāng)中。不用額外下載任何東西。結(jié)論,要想防木馬,所以盡量不要訪問(wèn)非正規(guī)網(wǎng)站。但如果一個(gè)正規(guī)網(wǎng)站被黑客破解,把網(wǎng)頁(yè)中間加了一段兒javascript。那你就只能自認(rèn)倒霉了。


課外閱讀:
以下的例子,是一個(gè)服務(wù)器對(duì)多個(gè)客戶(hù)端。我們的客戶(hù)端程序可以運(yùn)行很多遍,代表多個(gè)客戶(hù)。

/*in this frame work, many clients can access the server with many thread and many socket using only one port,
bbb client use bbb socket with bbb thread, by default, one port can accept 50 socket. */


import java.net.ServerSocket;
import java.io.*;
import java.net.Socket;

public class ThreadServers {

public static void main(String[] args) {
try {
/* public ServerSocket(int port)
throws IOExceptionCreates a server socket, bound to the specified port.
The maximum queue length for incoming connection indications (a request to connect) is set to 50. If a connection indication
arrives when the queue is full, the connection is refused.


public ServerSocket(int port,int backlog)
throws IOException Creates a server socket and binds it to the specified local port number, with the specified backlog.
The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection
indication arrives when the queue is full, the connection is refused.

*/
ServerSocket ss = new ServerSocket(8089);
for(;;){
/* here this ServerSocket can accept unlimited client socket.every time after
it accept one, it just come back from the loop, and block here on accept statement.
a new client corresponds to a new socket */
Socket s = ss.accept();
/* this reader get data from socket, then print in the console.
a new client corresponds to a new thread */
ReadThread reader = new ReadThread(s);
// WriteThread writer = new WriteThread(s);

/* WriteThread get the input from console, then write it to the network. */
reader.start();
/*in this case, we have to comment out the following statement because if there
are two clients, if we type in characters in the console, which clients do we
type in to send out to? so the example is made easier not to server to send
out, to make it work, you can make the server to pop up two windows, then one window
corresponds to one client, in window, if you type in some characters, you send them to this client. */
// writer.start();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}

}

 




以下是客戶(hù)端程序:

import java.net.Socket;
import java.net.*;
import java.io.*;

public class ThreadClients {

public static void main(String[] args) {
Socket s = null;
try {
/*a new client corresponds to a new socket*/
s = new Socket("localhost", 8089);
/* this reader get data from socket, then print out in the console. */
/* WriteThread get the input from console, then write it to the network. */
// ReadThread reader = new ReadThread(s);
/*a new client corresponds to a new thread*/
WriteThread writer = new WriteThread(s);
// reader.start();
writer.start();
}
catch (Exception ex) {
ex.printStackTrace();
}


}

}

 

/*this reader get data from socket, then print in the console. */


import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;

public class ReadThread extends Thread {
private Socket socket;
public ReadThread(Socket socket) {
this.socket = socket;
}
public void run(){
try {
BufferedReader in = new BufferedReader
(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while(true){
String line = in.readLine();
out.println(line+" coming back from server");
System.out.println(line);
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}

 

/*WriteThread get the input from console, then write it to the network.*/




import java.net.Socket;
import java.io.PrintWriter;
import java.io.*;

public class WriteThread extends Thread {
private Socket socket;
public WriteThread(Socket socket) {
this.socket = socket;
}
public void run(){
try {
/*PrintWriter(OutputStream out, boolean autoFlush)
Create a new PrintWriter from an existing OutputStream.
public PrintWriter(Writer out,boolean autoFlush) Create a new PrintWriter.
autoFlush - A boolean; if true, the println() methods will flush the output buffer */
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader inn = new BufferedReader
(new InputStreamReader(socket.getInputStream()));
BufferedReader in =new BufferedReader(new InputStreamReader(System.in));
for(;;){
String line = in.readLine();
out.println(line);
String linen = inn.readLine();
System.out.println(linen);

}
}
catch (IOException ex) {
}
}
}

 
when run,start server, then start several clients.