国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

黑馬程序員----java基礎--網(wǎng)絡編程

2019-11-15 01:12:50
字體:
來源:轉載
供稿:網(wǎng)友
黑馬程序員----java基礎--網(wǎng)絡編程

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------

一、網(wǎng)絡參考模型

1、OSI參考模型和TCP/ip 參考模型

七層描述:

(1). 物理層:主要定義物理設備標準,如網(wǎng)線的接口類型、光纖的接口類型、各種傳輸介質的傳輸速率等。它的主要作用是傳輸比特流。

(2). 數(shù)據(jù)鏈路層:主要將從物理層接收的數(shù)據(jù)進行MAC地址(網(wǎng)卡的地址)的封裝與解封裝。這一層工作的設備是交換機,數(shù)據(jù)通過交換機來傳輸。

(3). 網(wǎng)絡層:主要將下層接收到的數(shù)據(jù)進行IP地址(例,192.168.0.1)的封裝與解封裝。這一層工作的設備是路由器。。

(4). 傳輸層:定義了一些傳輸數(shù)據(jù)的協(xié)議和端口號(WWW端口號80等),主要是將從下層接收的數(shù)據(jù)進行分段和傳輸,到達目的地址后再進行重組。

(5). 會話層:通過傳輸層(端口號:傳輸端口與接收端口)建立數(shù)據(jù)傳輸?shù)耐贰V饕谀愕南到y(tǒng)之間發(fā)起會話或者接收會話請求(設備之間需要互相認識可以是IP也可以是MAC或者是主機名)。

(6). 表示層:主要是進行對接收的數(shù)據(jù)進行解釋,加密與解密、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉換成人能夠識別的東西(如圖片、聲音等)。

(7). 應用層:主要是一些終端的應用,比如說FTP(各種文件下載)、WEB(IE瀏覽)、QQ之類的(可以把它理解成我們在電腦屏幕上可以看到的東西,就是終端應用)。

注:

(1).每個網(wǎng)卡的MAC地址都是全球唯一的。

(2).路由器實現(xiàn)將數(shù)據(jù)包發(fā)送到指定的地點。

(3).應用軟件之間通信的過程就是層與層之間封包、解包的過程

(4).OSI參考模型雖然設計精細,但過于麻煩,效率不高,因此才產(chǎn)生了簡化版的TCP/IP參考模型。

2、網(wǎng)絡通信三要素:IP地址,端口號,傳輸協(xié)議。

(1)、IP地址:InetAdderss

1.它是網(wǎng)絡中的設備標識

2.不易記憶,可用主機名表示,兩者存在映射關系

3.IPV4數(shù)量已經(jīng)不夠分配,所以產(chǎn)生了IPV6

4.本地回環(huán)地址:127.0.0.1 主機名:localhost

5.在沒有連接互聯(lián)網(wǎng)的情況,為了讓訪問本機方便,所以分配了一個默認的IP地址,也就是本地回環(huán)地址

(2)、端口號

1.用于標識進程(應用程序)的邏輯地址,不同進程的標識

2.有效端口:0~65535,其中0~1024系統(tǒng)使用或保留端口。

3.沒有程序都有端口號用來定為應用程序

(3)、傳輸協(xié)議

這是通訊的規(guī)則。常見協(xié)議有:UDP、TCP。

UDP

1.將數(shù)據(jù)以及源和目的封裝成數(shù)據(jù)包中,不需要建立連接

2.每個數(shù)據(jù)包的大小限制在64k內(nèi)

3.因無連接,所以是不可靠的協(xié)議

4.不需要建立連接,速度快

應用案例:QQ聊天、視頻聊天、對講機、FeiQ、視頻教學等在線視頻都是UDP

TCP

1.建立連接,形成傳輸數(shù)據(jù)的通道

2.在連接中進行大數(shù)據(jù)量傳輸

3.通過三次握手完成連接,是可靠協(xié)議。三次握手:第一次本方發(fā)送請求,第二次對方確認連接,第三次本方確認對方連接成功。

4.必須建立連接,效率會稍低

應用案例:FTP文件傳輸、迅雷下載、打電話

3、java.net.InetAdderss常用網(wǎng)絡方法

無構造函數(shù),只能用方法返回本類對象

1 static  InetAddress    getLocalHost();//返回一個InetAdderss本類對象2 static  String    getHostName();//返回此ip地址的主機名3 static   String    getHostAddress();//返回ip地址字符串4 String    toString();//返回此ip地址的String表現(xiàn)形式5 static    InetAddress    getByName(String host);//獲取指定主機名的ip地址6 static  InetAddress[]    getAllByName(String host);//獲取指定主機名的全部ip地址

代碼演示:

 1 import java.net.*; 2 class InetAddressDemo  3 { 4     public static void main(String[] args) throws Exception 5     { 6         InetAddress ia= InetAddress.getLocalHost();//返回InetAddress本來對象 7         String name=ia.getHostName();//獲取IP地址的主機名 8         String ip=ia.getHostAddress();//獲取本地ip地址 9         System.out.

二、UDP協(xié)議-發(fā)送端和接收端

Socket:套接字,通信的端點。就是為網(wǎng)絡服務提供的一種機制,通信的兩端都有Socket,網(wǎng)絡通信其實就是Socket間的通信,數(shù)據(jù)在兩個Socket間通過IO傳輸。

1、DatagramSocket和DatagramPacket對象

(1)、DatagramSocket類常用方法

此類表示用來發(fā)送和接收數(shù)據(jù)報包的套接字。

1、構造方法

1 new    DatagramSocket();//構造數(shù)據(jù)報套接字并綁定到本地主機任何端口上,發(fā)送端2 new    DatagramSocket(int port);//創(chuàng)建數(shù)據(jù)報套接字并綁定到本地主機上的指定端口,接收端

2、一般方法

1 void    connect(InetAddress address,int port);//將套接字連接到此套接字的遠程地址上2 void    send(DatagramPacket p);//從此套接字發(fā)送數(shù)據(jù)包3 void    receive(DatagramPacket p);//從此套接字接收數(shù)據(jù)包4 InetAddress    getInetAddress();//返回此套接字連接的地址5 int    getPort();//返回此套接字的端口

(2)、DatagramPacket類常用方法

此類表示數(shù)據(jù)報包

1、構造方法

1 new    DatagramPacket(byte[] buf,int length,InetAddress address,int port);//構造數(shù)據(jù)報包,用來將長度為length的包發(fā)送到指定主機上的指定端口號2 new  DatatgramPacket(byte[] buf,int length);//構造 DatagramPacket,用來接收長度為 length 的數(shù)據(jù)包

2、一般方法

1 InetAddress    getAddress();//獲取某臺主機的ip地址2 byte[]    getData();//獲取數(shù)據(jù)緩沖區(qū)的內(nèi)容3 int    getLength();//獲取將要發(fā)送或者接收到的數(shù)據(jù)的長度4 int    getPort();//獲取某臺主機的端口號

2、UDP傳輸發(fā)送和獲取數(shù)據(jù)的步驟

UDP發(fā)送端步驟:

  1)、建立UDPSocket服務

  2)、提供數(shù)據(jù),并將數(shù)據(jù)封裝到數(shù)據(jù)包中

  3)、通過Socket服務的send方法,將數(shù)據(jù)包發(fā)送出去

  4)、關閉資源

UDP接收端步驟:

  1)、定義UDPSocket服務。通常會監(jiān)聽一個端口號。其實就是給這個接收網(wǎng)絡應用程序定義數(shù)字標識,方便于明確哪些數(shù)據(jù)過來哪個應該程序可以處理

  2)、定義一個數(shù)據(jù)包。因為要存儲接收到的字節(jié)數(shù)據(jù)。因為數(shù)據(jù)包對象中有更多功能可以提取字節(jié)數(shù)據(jù)中的不同數(shù)據(jù)信息

  3)、通過Sockt服務的receive方法將接收到的數(shù)據(jù)存入已經(jīng)定義好的數(shù)據(jù)包中

  4)、通過數(shù)據(jù)包對象的特有功能,將這些不同的數(shù)據(jù)取出,打印在控制臺上

  5)、關閉資源

需求:聊天程序(雙窗口模式)代碼演示:

 1 import java.io.*; 2 import java.net.*; 3 class UDPSend  4 { 5     public static void main(String[] args)  6     { 7         DatagramSocket ds=null;         8         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 9         try        10         {11             //1,創(chuàng)建udp服務。通過DatagramSocket對象。12             ds=new DatagramSocket();13             String line=null;14             while ((line=br.readLine())!=null)15             {16                 byte[] buf=line.getBytes();17                 //2,確定數(shù)據(jù),并封裝成數(shù)據(jù)包。DatagramPacket(byte[] buf,int length, InetAddress address, int port) 20                 DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.104"),55128);23                 //3,通過socket服務,將已有的數(shù)據(jù)包發(fā)送出去。通過send方法 。26                 ds.send(dp);27                 if("over".equals(line))28                     break;29             }30             31         }32         catch (Exception e)33         {34             System.out.println(e);35         }36         finally37         {38             if(ds!=null)39                 try40                 {41                     //4,關閉資源。42                     ds.close();43                 }44                 catch (Exception e)45                 {46                     System.out.println("發(fā)送端關閉失敗");47                 }48         }49     }50 }51 class UDPReceive52 {53     public static void main(String[] args){54         DatagramSocket ds=null;55         DatagramPacket dp=null;56         try{57             //1,創(chuàng)建udp socket,建立端點。58             ds=new DatagramSocket(55128);        59             while (true)60             {    //2,定義數(shù)據(jù)包。用于存儲數(shù)據(jù)。            61                 byte[] buf=new byte[1024];62                 dp=new DatagramPacket(buf,buf.length);63                 //3,通過服務的receive方法將收到數(shù)據(jù)存入數(shù)據(jù)包中。64                 ds.receive(dp);//阻塞式方法。65                 //4,通過數(shù)據(jù)包的方法獲取其中的數(shù)據(jù)。66                 String ip=dp.getAddress().getHostAddress();67                 String data=new String(dp.getData(),0,dp.getLength());68                 System.out.println(ip+"......"+data);69                 if(data.equals("over"))70                     break;71             }72             73         }74         catch (Exception e)75         {76             System.out.println(e);77         }78         finally79         {80             if(ds!=null)81                 try82                 {83                     //5,關閉資源84                     ds.close();85                 }86                 catch (Exception e)87                 {88                     System.out.println("接收端關閉失敗");89                 }90         }91     }92 }

需求:聊天程序(單窗口模式-群聊)代碼演示:

收數(shù)據(jù)的部分,和發(fā)數(shù)據(jù)的這兩部分需要同時執(zhí)行。那就需要用到多線程技術。一個線程控制收,一個線程控制發(fā)。因為收和發(fā)動作是不一致的,所以要定義兩個run方法。而且這兩個方法要封裝到不同的類中。

 1 import java.io.*; 2 import java.net.*; 3 class UDPSend implements Runnable 4 { 5     private DatagramSocket ds; 6     UDPSend(DatagramSocket ds){ 7         this.ds=ds; 8     } 9     public void run(){10         try11         {12             //讀取鍵盤錄入13             BufferedReader br=new BufferedReader(new InputStreamReader(System.in));14             String line=null;15             while ((line=br.readLine())!=null)16             {17                 byte[] buf=line.getBytes();18                 //定義數(shù)據(jù)包,用來存放數(shù)據(jù)19                 DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.104"),5556);20                 //通過send方法把數(shù)據(jù)發(fā)送給接收端21                 ds.send(dp);22                 if("over".equals(line))23                     break;24             }25             ds.close();26         }27         catch (Exception e)28         {29             System.out.println("發(fā)送失敗");30         }31     }32 }33 class UDPReceive implements Runnable34 {35     private DatagramSocket ds;36     UDPReceive(DatagramSocket ds){37         this.ds=ds;38     }39     public void run(){//復寫run方法40         try41         {42             while (true)43             {44                 byte[] buf=new byte[1024];45                 //定義數(shù)據(jù)包用來接收發(fā)送端發(fā)過來的數(shù)據(jù)信息46                 DatagramPacket dp=new DatagramPacket(buf,buf.length);47                 //接收數(shù)據(jù)48                 ds.receive(dp);49                 //對接收過來的數(shù)據(jù)進行ip地址等信息的解析50                 String ip=dp.getAddress().getHostAddress();51                 String data=new String(dp.getData(),0,dp.getLength());52                 System.out.println(ip+"......."+data);53                 if("over".equals(data))54                     break;55             }56             ds.close();            57         }58         catch (Exception e)59         {60             System.out.println("接收端接受失敗");61         }62     }63 }64 class ChatRoom65 {66     public static void main(String[] args)throws Exception{67         //定義兩個DatagramSocket服務68         DatagramSocket send=new DatagramSocket();69         DatagramSocket receive=new DatagramSocket(5556);70         //開啟兩個線程71         new Thread(new UDPSend(send)).start();72         new Thread(new UDPReceive(receive)).start();73     }74 }

三、TCP協(xié)議-客戶端和服務端

客戶端(Client)首先與服務端(Server)建立連接,形成通道(其實就是IO流),然后,數(shù)據(jù)就可以在通道之間進行傳輸,并且單個Server端可以同時與多個Client端建立連接。Socket和ServerSocket,建立客戶端和服務器端。建立連接后,通過Socket中的IO流進行數(shù)據(jù)的傳輸。關閉socket。同樣,客戶端與服務器端是兩個獨立的應用程序。

TCP客戶端

客戶端需要明確服務器的ip地址以及端口,這樣才可以去試著建立連接,如果連接失敗,會出現(xiàn)異常。連接成功,說明客戶端與服務端建立了通道,那么通過IO流就可以進行數(shù)據(jù)的傳輸,而Socket對象已經(jīng)提供了輸入流和輸出流對象,通過getInputStream()和getOutputStream()獲取即可與服務端通訊。結束后關閉Socket。客戶端,通過查閱socket對象,發(fā)現(xiàn)在該對象建立時,就可以去連接指定主機。因為tcp是面向連接的。所以在建立socket服務時,就要有服務端存在,并連接成功。形成通路后,在該通道進行數(shù)據(jù)的傳輸。

TCP服務端

服務端需要明確它要處理的數(shù)據(jù)是從哪個端口進入的。當有客戶端訪問時,要明確是哪個客戶端,可通過accept()獲取已連接的客戶端對象,并通過該對象與客戶端通過IO流進行數(shù)據(jù)傳輸。當該客戶端訪問結束,關閉該客戶端。1,建立服務端的socket服務。ServerSocket();并監(jiān)聽一個端口。2,獲取連接過來的客戶端對象。通過ServerSokcet的 accept方法。沒有連接就會等,所以這個方法阻塞式的。3,客戶端如果發(fā)過來數(shù)據(jù),那么服務端要使用對應的客戶端對象,并獲取到該客戶端對象的讀取流來讀取發(fā)過來的數(shù)據(jù)。并打印在控制臺。4,關閉服務端。(可選)。

TCP協(xié)議因為是面向連接的。所以傳輸數(shù)據(jù)必須先開服務端,再開客戶端。否則,客戶端根本連接不上服務端。

1、Socket類中常用方法

(1)、構造方法

1 new    Socket();2 new    Socket(InetAddress address,int port);//創(chuàng)建一個流套接字并將其連接到指定 IP 地址的指定端口號。3 new    Socket(String host,int port);// 創(chuàng)建一個流套接字并將其連接到指定主機上的指定端口號。

(2)、成員方法

1 void  bind(SocketAddress bindpoint);//將套接字綁定到本地地址。 2 void  connect(SocketAddress endpoint);//將此套接字連接到服務器。 3 InetAddress  getInetAddress();//返回套接字連接的地址。4 InputStream  getInputStream();//返回此套接字的輸入流。5 OutputStream  getOutputStream();// 返回此套接字的輸出流。 6 int  getPort();// 返回此套接字連接到的遠程端口 7 void  shutdownInput();// 此套接字的輸入流置于“流的末尾”。 8 void  shutdownOutput();// 禁用此套接字的輸出流 

2、ServerSocket類中常用方法

(1)、構造方法

1 new    ServerSocket();//創(chuàng)建非綁定服務器套接字。2 new    ServerSocket(int port);//創(chuàng)建綁定到特定端口的服務器套接字。

(2)、成員方法

1  Socket  accept();//偵聽并接受到此套接字的連接。 2 InetAddress  getInetAddress();// 返回此服務器套接字的本地地址。 

需求:TCP協(xié)議-服務端和客戶端交互代碼演示:

 1 import java.io.*; 2 import java.net.*; 3 class  TCPClient 4 { 5     public static void main(String[] args) throws Exception 6     { 7         //創(chuàng)建客戶端的socket服務。指定目的主機和端口 8         Socket s=new Socket("192.168.1.100",5544); 9         //為了發(fā)送數(shù)據(jù),應該獲取socket流中的輸出流。10         OutputStream out=s.getOutputStream();11         out.write("TCP,我來了!".getBytes());12         InputStream in=s.getInputStream();13         byte[] buf=new byte[1024];14         int len=in.read(buf);15         System.out.println(new String(buf,0,len));16         s.close();17     }18 }19 class TCPServer20 {21     public static void main(String[] args)throws Exception{22         //建立服務端socket服務。并監(jiān)聽一個端口。23         ServerSocket ss=new ServerSocket(5544);24         //通過accept方法獲取連接過來的客戶端對象。25         Socket s=ss.accept();26         //獲取ip地址27         String ip=s.getInetAddress().getHostAddress();28         System.out.println(ip+".....connnect");29         //獲取客戶端發(fā)送過來的數(shù)據(jù),那么要使用客戶端對象的讀取流來讀取數(shù)據(jù)。30         InputStream in=s.getInputStream();31         byte[] buf=new byte[1024];32         int len=in.read(buf);33         System.out.println(new String(buf,0,len));34 35         OutputStream out=s.getOutputStream();36         out.write("收到".getBytes());37         ss.close();38         //關閉客戶端.39         s.close();40     }41 }

需求:建立一個文本轉換服務器。

客戶端給服務端發(fā)送文本,服務單會將文本轉成大寫在返回給客戶端。而且客戶度可以不斷的進行文本轉換。當客戶端輸入over時,轉換結束。

客戶端:

既然是操作設備上的數(shù)據(jù),那么就可以使用io技術,并按照io的操作規(guī)律來思考。

源:鍵盤錄入。

目的:網(wǎng)絡設備,網(wǎng)絡輸出流。

而且操作的是文本數(shù)據(jù)。可以選擇字符流。

步驟

1,建立服務。

2,獲取鍵盤錄入。

3,將數(shù)據(jù)發(fā)給服務端。

4,后去服務端返回的大寫數(shù)據(jù)。

5,結束,關資源。

都是文本數(shù)據(jù),可以使用字符流進行操作,同時提高效率,加入緩沖。

服務端:

源:socket讀取流。

目的:socket輸出流。

都是文本,裝飾。

 1 import java.io.*; 2 import java.net.*; 3 class TransClient  4 { 5     public static void main(String[] args) throws Exception 6     { 7         Socket s=new Socket("192.168.1.100",7788); 8         //定義讀取鍵盤數(shù)據(jù)的流對象。 9         BufferedReader br=new BufferedReader(new InputStreamReader(System.in));10         //定義目的,將數(shù)據(jù)寫入到socket輸出流。發(fā)給服務端。11         PrintWriter out=new PrintWriter(s.getOutputStream(),true);12         //定義一個socket讀取流,讀取服務端返回的大寫信息。13         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));14         String line=null;15         while ((line=br.readLine())!=null)16         {17             out.println(line);18             if("over".equals(line))19                 break;20             String info=in.readLine();        21             System.out.println("info="+info);22         }23         s.close();24 25     }26 }27 class TransServer28 {29     public static void main(String[] args)throws Exception{30         ServerSocket ss=new ServerSocket(7788);        31         Socket s=ss.accept();32         System.out.println(s.getInetAddress().getHostAddress()+".....connect");33         //讀取socket讀取流中的數(shù)據(jù)。34         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));35         //目的。socket輸出流。將大寫數(shù)據(jù)寫入到socket輸出流,并發(fā)送給客戶端。36         PrintWriter out=new PrintWriter(s.getOutputStream(),true);37         String line=null;38         while ((line=in.readLine())!=null)39         {40             System.out.println(line);41             out.println(line.toUpperCase());42             if("over".equals(line))43                 break;44         }45         s.close();46         ss.close();47     }48 }

需求:TCP協(xié)議上傳文本文件

 1 import java.io.*; 2 import java.net.*; 3 class  TCPClient 4 { 5     public static void main(String[] args)throws Exception 6     { 7         Socket s=new Socket("192.168.1.100",9999); 8         BufferedReader br=new BufferedReader(new FileReader("TCPDemo.java")); 9         PrintWriter out=new PrintWriter(s.getOutputStream(),true);10         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));11         String line=null;12         while ((line=br.readLine())!=null)13         {14             out.println(line);15         }16         s.shutdownOutput();//關閉客戶端的輸出流。相當于給流中加入一個結束標記-1.17         System.out.println(in.readLine());18         s.close();19         br.close();20     }21 }22 class TCPServer23 {24     public static void main(String[] args)throws Exception{25         ServerSocket ss=new ServerSocket(9999);26         Socket s=ss.accept();27         System.out.println(s.getInetAddress().getHostAddress()+"....connect");28         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));29         PrintWriter pw=new PrintWriter(new FileWriter("E://TCPDemo.java"),true);30         PrintWriter out=new PrintWriter(s.getOutputStream(),true);31         String line=null;32         while ((line=in.readLine())!=null)33         {34             pw.println(line);35         }36         out.println("上傳成功");37         s.close();38         ss.close();39         pw.close();40     }41 }

需求:TCP客戶端并發(fā)上傳圖片代碼演示:

服務端最好就是將每個客戶端封裝到一個單獨的線程中,這樣,就可以同時處理多個客戶端請求。

如何定義線程呢?

只要明確了每一個客戶端要在服務端執(zhí)行的代碼即可。將該代碼存入run方法中。

 1 import java.io.*; 2 import java.net.*; 3 class PicClient 4 { 5     public static void main(String[] args)throws Exception{ 6         File file=new File(args[0]); 7         if(!(file.exists()&& file.isFile())){ 8             System.out.println("請上傳圖片"); 9             return;10         }11         if(!(file.getName().endsWith(".jpg"))){12             System.out.println("上傳格式錯誤");13             return;14         }15         if(file.length()>=1024*1024*4){16             System.out.println("文件過大,請切割后上傳");17             return;18         }19 20         Socket s=new Socket("192.168.1.104",5555);21         FileInputStream fis=new FileInputStream(file);22         OutputStream out=s.getOutputStream();23         byte[] buf=new byte[1024];24         int len=0;25         while ((len=fis.read(buf))!=-1)26         {27             out.write(buf,0,len);28         }29         s.shutdownOutput();//告訴服務端數(shù)據(jù)已寫完30         InputStream in=s.getInputStream();31         byte[] bufIn=new byte[1024];32         int num=in.read(bufIn);33         System.out.println(new String(bufIn,0,num));34         s.close();35         fis.close();36     }37 }38 class PicThread implements Runnable39 {40     private Socket s;41     PicThread(Socket s){42         this.s=s;43     }44     public void run(){45         String ip=s.getInetAddress().getHostAddress();46         System.out.println(ip+".....connect");47         try48         {49             int count=1;50             //創(chuàng)建file對象51             File file=new File("E://"+ip+"("+count+")"+".jpg");52             //如果file文件存在則count++,直到不存在為止53             while(file.exists())54                 file=new File("E://"+ip+"("+(count++)+")"+".jpg");55             InputStream in=s.getInputStream();56             FileOutputStream fos=new FileOutputStream(file);57             byte[] buf=new byte[1024];58             int len=0;59             while ((len=in.read(buf))!=-1)60             {61                 fos.write(buf,0,len);62             }63             OutputStream out=s.getOutputStream();64             out.write("上傳成功".getBytes());65             s.close();            66         }67         catch (Exception e)68         {69             System.out.println(ip+"連接成功");70         }71     }72 }73 class PicServer74 {75     public static void main(String[] args)throws Exception{76         ServerSocket ss=new ServerSocket(5555);77         while (true)78         {79             Socket s=ss.accept();80             new Thread(new PicThread(s)).start();81         }82     }83 }

需求:客戶端通過鍵盤錄入用戶名。服務端對這個用戶名進行校驗。最多就登錄三次。

如果該用戶存在,在服務端顯示xxx,已登陸。

并在客戶端顯示 xxx,歡迎光臨。

如果該用戶不存在,在服務端顯示xxx,嘗試登陸。

并在客戶端顯示 xxx,該用戶不存在。

 1 import java.io.*; 2 import java.net.*; 3 class LoginClient  4 { 5     public static void main(String[] args)throws Exception 6     { 7         Socket s=new Socket("192.168.1.104",6666); 8         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 9         //讀取socket流中的讀取流10         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));11         //socket流中的輸出流12         PrintWriter out=new PrintWriter(s.getOutputStream(),true);    13         //循環(huán)3次輸入,如果輸入為null,直接停止輸入14         for (int x=0;x<3 ;x++ )15         {16             String name=br.readLine();17             if(name==null)18                 break;19             out.println(name);20             String info=in.readLine();21             System.out.println(info);22             //如果獲取到流中有“歡迎“字樣,說明對方已經(jīng)登錄,這時候即使輸入的不到3次,也停止輸入,因為已經(jīng)登錄成功了。23             if(info.contains("歡迎")){                24                 break;25             }26         }27         s.close();28     }29 }30 class LoginThread implements Runnable31 {32     private Socket s;33     LoginThread(Socket s){34         this.s=s;35     }36     public void run(){37         String ip=s.getInetAddress().getHostAddress();38         System.out.println(ip+".....connect");39         try40         {                41             for (int x=0;x<3 ;x++ )42             {43                 //讀取socket流中的輸入流44                 BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream()));45                 String name=in.readLine();46                 if(name==null)47                     break;48                 //讀取文件49                 BufferedReader br=new BufferedReader(new FileReader("Userinfo.txt"));50                 //socket流輸出流51                 PrintWriter out=new PrintWriter(s.getOutputStream(),true);    52                 //定義一個標記, 從socket輸入流中的鍵盤數(shù)據(jù)判斷user.txt中是否有name符合,如果有標記為真,跳出while循環(huán)。53                 boolean flag=false;54                 String line=null;55                 while ((line=br.readLine())!=null)56                 {57                     //判斷Userinfo.txt和name是否有相同的58                     if(line.equals(name)){59                         flag=true;60                         break;61                     }62                 }63                 if(flag){64                     System.out.println(name+",已登陸");65                     out.println(name+",歡迎光臨");66                     break;67                 }68                 else{69                     System.out.println(name+",嘗試登陸");70                     out.println(name+",該用戶不存在");71                 }72             }73             s.close();74         }75         catch (Exception e)76         {77             System.out.println(ip+"連接失敗");78         }79     }80 }81 class LoginServer82 {83     public static void main(String[] args)throws Exception{84         ServerSocket ss=new ServerSocket(6666);85         while (true)86         {87             Socket s=ss.accept();88             new Thread(new LoginThread(s)).start();89         }90     }91 }

四、客戶端和服務器端原理

最常見的客戶端:瀏覽器,IE/Chrome

最常見的服務端:服務器,Tomcat。

1. 自定義服務端

使用已有的客戶端IE,了解一下客戶端向服務端發(fā)了什么請求

 1 import java.io.*; 2 import java.net.*; 3 class ServerDemo  4 { 5     public static void main(String[] args) throws Exception 6     { 7         ServerSocket  ss=new ServerSocket(8080); 8         Socket s=ss.accept(); 9         PrintWriter out=new PrintWriter(s.getOutputStream(),true);10         out.println("<font size='5' color='red'>客戶端你好 </font>");11         //獲取到服務器向客戶端發(fā)送的數(shù)據(jù)12         InputStream is=s.getInputStream();        13         byte[] buf=new byte[1024];        14         int len=is.read(buf);15         System.out.println(new String(buf,0,len));16         ss.close();17         s.close();        18     }19 }20 /*這是服務器向客戶端發(fā)送的數(shù)據(jù)21 (請求行,請求方式:GET;請求的資源路徑:/;HTTP協(xié)議版本:1.1。)22 GET / HTTP/1.123 (請求消息頭,屬性名:屬性值)24 Host: 127.0.0.1:808025 Connection: keep-alive26 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=027 .828 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like29 Gecko) Chrome/42.0.2311.152 Safari/537.3630 Accept-Encoding: gzip, deflate, sdch31 Accept-Language: zh-CN,zh;q=0.832 */

HTTP是一個客戶端和服務端請求和應答的標準,客戶端按照HTTP的標準發(fā)送數(shù)據(jù)到服務端,服務端按照HTTP的標準解析收到的數(shù)據(jù)。很多軟件都內(nèi)置了此標準。

2. 模擬一個瀏覽器獲取信息。

 1 import java.net.*; 2 import java.io.*; 3 public class MyBrowser 4 { 5         public static void main(String[] args) throws IOException {                 6                 Socket s = new Socket("192.168.1.100",8080); 7                 //模擬瀏覽器,向tomcat服務端發(fā)送符合http協(xié)議的請求消息。 8                 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 9                 out.println("GET /myweb/1.html HTTP/1.1");10                 out.println("Accept: */*");11                 out.println("Host: 192.168.1.100:8080");12                 out.println("Connection: close");13                 out.println();14                 out.println();15                 InputStream in = s.getInputStream();16                 byte[] buf = new byte[1024];17                 int len = in.read(buf);18                 String str = new String(buf,0,len);19                 System.out.println(str);20                 s.close();21         }22 }

HTTP服務端發(fā)回的應答消息:

(應答行,HTTP的協(xié)議版本:1.1;應答狀態(tài)碼:200;應答狀態(tài)描述信息:OK。)

HTTP/1.1 200 OK

(應答消息屬性信息,屬性名:屬性值。)

Server: Apache-Coyote/1.1

Accept-Ranges: bytes

ETag: W/"211-1433908112666"

Last-Modified: Wed, 10 Jun 2015 03:48:32 GMT

Content-Type: text/html

Content-Length: 211

Date: Wed, 10 Jun 2015 03:52:16 GMT

Connection: close

應答行中屬性名及屬性值的具體含義,初學者不用追究,在JavaWeb課程中將會深入講解。

五、URL和URLConnection類

URI:統(tǒng)一資源標示符。

URL:統(tǒng)一資源定位符,也就是說根據(jù)URL能夠定位到網(wǎng)絡上的某個資源,它是指向互聯(lián)網(wǎng)“資源”的指針。每個URL都是URI,但不一定每個URI都是URL。這是因為URI還包括一個子類,即統(tǒng)一資源名稱(URN),它命名資源但不指定如何定位資源。

URL類可以建立到遠程對象的連接,也就是說這里面封裝了socket,可以直接獲取socket流。

1、常用方法

1 String   getFile();//獲取此 URL 的文件名。 2 String   getHost();//獲取此 URL 的主機名(如果適用)。 3 String   getPath();//獲取此 URL 的路徑部分。 4 int      getPort();//獲取此 URL 的端口號。 5 String   getProtocol();//獲取此 URL 的協(xié)議名稱。 6 String   getQuery();//獲取此 URL 的查詢部分。7 URLConnection   openConnection();//返回一個 URLConnection 對象,它表示到 URL 所引用的遠程對象的連接。8 InputStream   openStream();//打開到此 URL 的連接并返回一個用于從該連接讀入的 InputStream。此方法是下面方法的縮寫: 9 openConnection().getInputStream()。

代碼演示:

 1 import java.net.*; 2 import java.io.*; 3 class  URLConnectionDemo 4 { 5     public static void main(String[] args) throws Exception 6     { 7         URL url = new URL("http://192.168.1.254:8080/myweb/demo.html"); 8  9         URLConnection conn = url.openConnection();10         System.out.println(conn);11         12         InputStream in = conn.getInputStream();13 14         byte[] buf = new byte[1024];15 16         int len = in.read(buf);17 18         System.out.println(new String(buf,0,len));

之所以運行結果中響應頭不見了,只能看到主體數(shù)據(jù)的原因在于:URLConnection對象已經(jīng)把響應頭給解析了。

六、域名解析

在瀏覽器中輸入新浪的域名,DNS解析域名成IP,然后計算機再通過獲取到的IP訪問新浪服務器。

域名解析,最先走是本地的hosts(C:/WINDOWS/system32/drivers/etc/hosts)文件,解析失敗了,才去訪問DNS服務器解析、獲取IP地址。

可以通過hosts文件可以屏蔽游戲網(wǎng)站內(nèi)容彈出。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 邮箱| 清远市| 余庆县| 德昌县| 文水县| 阳新县| 乐东| 绥江县| 文安县| 阳高县| 高清| 老河口市| 盐城市| 黄冈市| 青川县| 望都县| 金华市| 宁陵县| 洪雅县| 新兴县| 桐梓县| 广元市| 金华市| 大理市| 环江| 泰来县| 庆元县| 南通市| 白山市| 会宁县| 治多县| 双辽市| 神农架林区| 云龙县| 丰县| 溧水县| 仪征市| 桦南县| 于都县| 宜昌市| 探索|