Java基礎(chǔ)語法_Day23

一、網(wǎng)絡(luò)編程概述
  • 網(wǎng)絡(luò)協(xié)議
  • 通過計(jì)算機(jī)網(wǎng)絡(luò)可以使多臺計(jì)算機(jī)實(shí)現(xiàn)連接拌屏,位于同一個網(wǎng)絡(luò)中的計(jì)算機(jī)在進(jìn)行連接和通信時需要遵守一定的規(guī)則被廓,這就好比在道路中行駛的汽車一定要遵守交通規(guī)則一樣。在計(jì)算機(jī)網(wǎng)絡(luò)中谅海,這些連接和通信的規(guī)則被稱為網(wǎng)絡(luò)通信協(xié)議脸哀,它對數(shù)據(jù)的傳輸格式、傳輸速率扭吁、傳輸步驟等做了統(tǒng)一規(guī)定撞蜂,通信雙方必須同時遵守才能完成數(shù)據(jù)交換。
  • 網(wǎng)絡(luò)通信協(xié)議有很多種侥袜,目前應(yīng)用最廣泛的是TCP/IP協(xié)議(Transmission Control Protocal/Internet Protoal傳輸控制協(xié)議/英特網(wǎng)互聯(lián)協(xié)議)蝌诡,它是一個包括TCP協(xié)議和IP協(xié)議,UDP(User Datagram Protocol)協(xié)議和其它一些協(xié)議的協(xié)議組枫吧,在學(xué)習(xí)具體協(xié)議之前首先了解一下TCP/IP協(xié)議組的層次結(jié)構(gòu)浦旱。
  • 在進(jìn)行數(shù)據(jù)傳輸時,要求發(fā)送的數(shù)據(jù)與收到的數(shù)據(jù)完全一樣九杂,這時颁湖,就需要在原有的數(shù)據(jù)上添加很多信息,以保證數(shù)據(jù)在傳輸過程中數(shù)據(jù)格式完全一致例隆。TCP/IP協(xié)議的層次結(jié)構(gòu)比較簡單爷狈,共分為四層,如圖所示裳擎。


    TCP/IP網(wǎng)絡(luò)模型.png

    上圖中涎永,TCP/IP協(xié)議中的四層分別是應(yīng)用層、傳輸層鹿响、網(wǎng)絡(luò)層和鏈路層羡微,每層分別負(fù)責(zé)不同的通信功能,接下來針對這四層進(jìn)行詳細(xì)地講解惶我。

    • 鏈路層:鏈路層是用于定義物理傳輸通道妈倔,通常是對某些網(wǎng)絡(luò)連接設(shè)備的驅(qū)動協(xié)議,例如針對光纖绸贡、網(wǎng)線提供的驅(qū)動盯蝴。
    • 網(wǎng)絡(luò)層:網(wǎng)絡(luò)層是整個TCP/IP協(xié)議的核心,它主要用于將傳輸?shù)臄?shù)據(jù)進(jìn)行分組听怕,將分組數(shù)據(jù)發(fā)送到目標(biāo)計(jì)算機(jī)或者網(wǎng)絡(luò)捧挺。
    • 傳輸層:主要使網(wǎng)絡(luò)程序進(jìn)行通信,在進(jìn)行網(wǎng)絡(luò)通信時,可以采用TCP協(xié)議,也可以采用UDP協(xié)議诚些。
    • 應(yīng)用層:主要負(fù)責(zé)應(yīng)用程序的協(xié)議邓尤,例如HTTP協(xié)議咽块、FTP協(xié)議等演训。
  • IP地址和端口號
  • 要想使網(wǎng)絡(luò)中的計(jì)算機(jī)能夠進(jìn)行通信庙楚,必須為每臺計(jì)算機(jī)指定一個標(biāo)識號失受,通過這個標(biāo)識號來指定接受數(shù)據(jù)的計(jì)算機(jī)或者發(fā)送數(shù)據(jù)的計(jì)算機(jī)很魂。
  • 在TCP/IP協(xié)議中扎酷,這個標(biāo)識號就是IP地址,它可以唯一標(biāo)識一臺計(jì)算機(jī)遏匆,目前霞玄,IP地址廣泛使用的版本是IPv4,它是由4個字節(jié)大小的二進(jìn)制數(shù)來表示拉岁,如:00001010000000000000000000000001坷剧。由于二進(jìn)制形式表示的IP地址非常不便記憶和處理,因此通常會將IP地址寫成十進(jìn)制的形式喊暖,每個字節(jié)用一個十進(jìn)制數(shù)字(0-255)表示惫企,數(shù)字間用符號“.”分開,如 “192.168.1.100”陵叽。
  • 隨著計(jì)算機(jī)網(wǎng)絡(luò)規(guī)模的不斷擴(kuò)大狞尔,對IP地址的需求也越來越多,IPV4這種用4個字節(jié)表示的IP地址面臨枯竭巩掺,因此IPv6 便應(yīng)運(yùn)而生了偏序,IPv6使用16個字節(jié)表示IP地址,它所擁有的地址容量約是IPv4的8×1028倍胖替,達(dá)到2128個(算上全零的)研儒,這樣就解決了網(wǎng)絡(luò)地址資源數(shù)量不夠的問題。
  • 通過IP地址可以連接到指定計(jì)算機(jī)独令,但如果想訪問目標(biāo)計(jì)算機(jī)中的某個應(yīng)用程序端朵,還需要指定端口號。在計(jì)算機(jī)中燃箭,不同的應(yīng)用程序是通過端口號區(qū)分的冲呢。端口號是用兩個字節(jié)(16位的二進(jìn)制數(shù))表示的,它的取值范圍是0到65535招狸,其中敬拓,0到1023之間的端口號用于一些知名的網(wǎng)絡(luò)服務(wù)和應(yīng)用,用戶的普通應(yīng)用程序需要使用1024以上的端口號裙戏,從而避免端口號被另外一個應(yīng)用或服務(wù)所占用乘凸。
  • 接下來通過一個圖例來描述IP地址和端口號的作用,如下圖所示挽懦。


    IP地址和端口號的作用.png

    從上圖中可以清楚地看到翰意,位于網(wǎng)絡(luò)中一臺計(jì)算機(jī)可以通過IP地址去訪問另一臺計(jì)算機(jī),并通過端口號訪問目標(biāo)計(jì)算機(jī)中的某個應(yīng)用程序信柿。

  • InetAddress

了解了IP地址的作用冀偶,我們看學(xué)習(xí)下JDK中提供了一個InetAdderss類,該類用于封裝一個IP地址渔嚷,并提供了一系列與IP地址相關(guān)的方法进鸠,下表中列出了InetAddress類的一些常用方法。


常用方法.png
  • 案例代碼一:
package com.neuedu.demo;

import java.net.InetAddress;
import java.net.UnknownHostException;

/*
* InetAddress:此類表示互聯(lián)網(wǎng)協(xié)議 (IP) 地址形病。 
* 
*/
public class InetAddressDemo {
  public static void main(String[] args) throws UnknownHostException   {
      //static InetAddress getByName(String host) 
       //InetAddress address = InetAddress.getByName("itheima");
      InetAddress address = InetAddress.getByName("192.168.1.107");//ip地址是唯一的
  
      //System.out.println(address);//itheima/192.168.1.107 ipconfig
      
      String hostAddress = address.getHostAddress();//192.168.1.107 返回IP地址
      String hostName = address.getHostName();//itheima   返回主機(jī)名
      
      System.out.println(hostAddress);
      System.out.println(hostName);


  }
}
二客年、UDP協(xié)議
  • UDP是無連接通信協(xié)議,即在數(shù)據(jù)傳輸時漠吻,數(shù)據(jù)的發(fā)送端和接收端不建立邏輯連接量瓜。簡單來說,當(dāng)一臺計(jì)算機(jī)向另外一臺計(jì)算機(jī)發(fā)送數(shù)據(jù)時途乃,發(fā)送端不會確認(rèn)接收端是否存在绍傲,就會發(fā)出數(shù)據(jù),同樣接收端在收到數(shù)據(jù)時耍共,也不會向發(fā)送端反饋是否收到數(shù)據(jù)烫饼。
  • 由于使用UDP協(xié)議消耗資源小,通信效率高试读,所以通常都會用于音頻杠纵、視頻和普通數(shù)據(jù)的傳輸例如視頻會議都使用UDP協(xié)議,因?yàn)檫@種情況即使偶爾丟失一兩個數(shù)據(jù)包钩骇,也不會對接收結(jié)果產(chǎn)生太大影響比藻。
  • 但是在使用UDP協(xié)議傳送數(shù)據(jù)時,由于UDP的面向無連接性倘屹,不能保證數(shù)據(jù)的完整性韩容,因此在傳輸重要數(shù)據(jù)時不建議使用UDP協(xié)議。UDP的交換過程如下圖所示唐瀑。


    UDP的交換過程.png
  • DatagramPacket
  • 前面介紹了UDP是一種面向無連接的協(xié)議群凶,因此,在通信時發(fā)送端和接收端不用建立連接哄辣。UDP通信的過程就像是貨運(yùn)公司在兩個碼頭間發(fā)送貨物一樣请梢。在碼頭發(fā)送和接收貨物時都需要使用集裝箱來裝載貨物,UDP通信也是一樣力穗,發(fā)送和接收的數(shù)據(jù)也需要使用“集裝箱”進(jìn)行打包毅弧,為此JDK中提供了一個DatagramPacket類,該類的實(shí)例對象就相當(dāng)于一個集裝箱当窗,用于封裝UDP通信中發(fā)送或者接收的數(shù)據(jù)够坐。
  • 想要創(chuàng)建一個DatagramPacket對象,首先需要了解一下它的構(gòu)造方法。在創(chuàng)建發(fā)送端和接收端的DatagramPacket對象時元咙,使用的構(gòu)造方法有所不同梯影,接收端的構(gòu)造方法只需要接收一個字節(jié)數(shù)組來存放接收到的數(shù)據(jù),而發(fā)送端的構(gòu)造方法不但要接收存放了發(fā)送數(shù)據(jù)的字節(jié)數(shù)組庶香,還需要指定發(fā)送端IP地址和端口號甲棍。
  • 接下來根據(jù)API文檔的內(nèi)容,對DatagramPacket的構(gòu)造方法進(jìn)行逐一詳細(xì)地講解赶掖。


    DatagramPacket的構(gòu)造方法1.png

    使用該構(gòu)造方法在創(chuàng)建DatagramPacket對象時感猛,指定了封裝數(shù)據(jù)的字節(jié)數(shù)組和數(shù)據(jù)的大小,沒有指定IP地址和端口號奢赂。很明顯陪白,這樣的對象只能用于接收端,不能用于發(fā)送端膳灶。因?yàn)榘l(fā)送端一定要明確指出數(shù)據(jù)的目的地(ip地址和端口號)咱士,而接收端不需要明確知道數(shù)據(jù)的來源,只需要接收到數(shù)據(jù)即可袖瞻。


    DatagramPacket的構(gòu)造方法2.png

    使用該構(gòu)造方法在創(chuàng)建DatagramPacket對象時司致,不僅指定了封裝數(shù)據(jù)的字節(jié)數(shù)組和數(shù)據(jù)的大小,還指定了數(shù)據(jù)包的目標(biāo)IP地址(address)和端口號(port)聋迎。該對象通常用于發(fā)送端脂矫,因?yàn)樵诎l(fā)送數(shù)據(jù)時必須指定接收端的IP地址和端口號,就好像發(fā)送貨物的集裝箱上面必須標(biāo)明接收人的地址一樣霉晕。
  • 上面我們講解了DatagramPacket的構(gòu)造方法庭再,接下來對DatagramPacket類中的常用方法進(jìn)行詳細(xì)地講解,如下表所示牺堰。


    常用方法.png
  • DatagramSocket
  • DatagramPacket數(shù)據(jù)包的作用就如同是“集裝箱”拄轻,可以將發(fā)送端或者接收端的數(shù)據(jù)封裝起來。然而運(yùn)輸貨物只有“集裝箱”是不夠的伟葫,還需要有碼頭恨搓。在程序中需要實(shí)現(xiàn)通信只有DatagramPacket數(shù)據(jù)包也同樣不行,為此JDK中提供的一個DatagramSocket類筏养。DatagramSocket類的作用就類似于碼頭斧抱,使用這個類的實(shí)例對象就可以發(fā)送和接收DatagramPacket數(shù)據(jù)包,發(fā)送數(shù)據(jù)的過程如下圖所示渐溶。


    發(fā)送數(shù)據(jù)過程.png
  • 在創(chuàng)建發(fā)送端和接收端的DatagramSocket對象時辉浦,使用的構(gòu)造方法也有所不同,下面對DatagramSocket類中常用的構(gòu)造方法進(jìn)行講解茎辐。


    構(gòu)造方法.png

    該構(gòu)造方法用于創(chuàng)建發(fā)送端的DatagramSocket對象宪郊,在創(chuàng)建DatagramSocket對象時掂恕,并沒有指定端口號,此時弛槐,系統(tǒng)會分配一個沒有被其它網(wǎng)絡(luò)程序所使用的端口號懊亡。


    構(gòu)造方法.png

    該構(gòu)造方法既可用于創(chuàng)建接收端的DatagramSocket對象,又可以創(chuàng)建發(fā)送端的DatagramSocket對象丐黄,在創(chuàng)建接收端的DatagramSocket對象時斋配,必須要指定一個端口號孔飒,這樣就可以監(jiān)聽指定的端口灌闺。
  • 上面我們講解了DatagramSocket的構(gòu)造方法,接下來對DatagramSocket類中的常用方法進(jìn)行詳細(xì)地講解坏瞄。
常用方法.png
  • UDP實(shí)現(xiàn)
  • 案例代碼二:
package com.neuedu.demo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
* 使用UDP協(xié)議發(fā)送數(shù)據(jù)
*     創(chuàng)建發(fā)送端Socket對象
*     創(chuàng)建數(shù)據(jù)并打包
*     發(fā)送數(shù)據(jù)
*     釋放資源
* 
* DatagramSocket:此類表示用來發(fā)送和接收數(shù)據(jù),基于UDP協(xié)議的
* 
* DatagramSocket() :創(chuàng)建Socket對象并隨機(jī)分配端口號
* DatagramSocket(int port) :創(chuàng)建Socket對象并指定端口號
*/
public class SendDemo {
  public static void main(String[] args) throws IOException  {
      //創(chuàng)建發(fā)送端Socket對象
      DatagramSocket ds = new DatagramSocket();
      //創(chuàng)建數(shù)據(jù)并打包
      /*
       * DatagramPacket :此類表示數(shù)據(jù)報包
       * 數(shù)據(jù) byte[]
       * 設(shè)備的地址 ip
       * 進(jìn)程的地址  端口號
         DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
       */
      
      String s = "hello udp,im comming!";
      byte[] bys = s.getBytes();
      int length = bys.length;
      InetAddress address = InetAddress.getByName("itheima");//發(fā)送給當(dāng)前設(shè)備
      int port = 8888;
      //打包
      DatagramPacket dp = new DatagramPacket(bys,length,address,port);
      //發(fā)送數(shù)據(jù)
      ds.send(dp);
      //釋放資源
      ds.close();
  }
}
package com.neuedu.demo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
* 使用UDP協(xié)議接收數(shù)據(jù)
*     創(chuàng)建接收端Socket對象
*     接收數(shù)據(jù)
*     解析數(shù)據(jù)
*     輸出數(shù)據(jù)
*     釋放資源
*
*/
public class ReceiveDemo {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建接收端Socket對象
      DatagramSocket ds = new DatagramSocket(8888);
      //接收數(shù)據(jù)
      //DatagramPacket(byte[] buf, int length) 
      byte[] bys = new byte[1024];
      DatagramPacket dp = new DatagramPacket(bys,bys.length);
              
      System.out.println(1);
      ds.receive(dp);//阻塞
      System.out.println(2);
      
      //解析數(shù)據(jù)
      //InetAddress getAddress() : 獲取發(fā)送端的IP對象
      InetAddress address = dp.getAddress();
      //byte[] getData()  :獲取接收到的數(shù)據(jù)桂对,也可以直接使用創(chuàng)建包對象時的數(shù)組
      byte[] data = dp.getData();
      //int getLength()  :獲取具體收到數(shù)據(jù)的長度
      int length = dp.getLength();
      
      
      
      //輸出數(shù)據(jù)
      System.out.println("sender ---> " + address.getHostAddress());
      //System.out.println(new String(data,0,length));
      System.out.println(new String(bys,0,length));
      //釋放資源
      ds.close();

  }
}
三、TCP協(xié)議
  • TCP通信同UDP通信一樣鸠匀,都能實(shí)現(xiàn)兩臺計(jì)算機(jī)之間的通信蕉斜,通信的兩端都需要創(chuàng)建socket對象。
  • 區(qū)別在于缀棍,UDP中只有發(fā)送端和接收端宅此,不區(qū)分客戶端與服務(wù)器端,計(jì)算機(jī)之間可以任意地發(fā)送數(shù)據(jù)爬范。
  • 而TCP通信是嚴(yán)格區(qū)分客戶端與服務(wù)器端的父腕,在通信時,必須先由客戶端去連接服務(wù)器端才能實(shí)現(xiàn)通信青瀑,服務(wù)器端不可以主動連接客戶端璧亮,并且服務(wù)器端程序需要事先啟動,等待客戶端的連接斥难。
  • 在JDK中提供了兩個類用于實(shí)現(xiàn)TCP程序枝嘶,一個是ServerSocket類,用于表示服務(wù)器端哑诊,一個是Socket類群扶,用于表示客戶端。
  • 通信時镀裤,首先創(chuàng)建代表服務(wù)器端的ServerSocket對象竞阐,該對象相當(dāng)于開啟一個服務(wù),并等待客戶端的連接淹禾,然后創(chuàng)建代表客戶端的Socket對象向服務(wù)器端發(fā)出連接請求馁菜,服務(wù)器端響應(yīng)請求,兩者建立連接開始通信铃岔。
  • ServerSocket

通過前面的學(xué)習(xí)知道汪疮,在開發(fā)TCP程序時峭火,首先需要創(chuàng)建服務(wù)器端程序。JDK的java.net包中提供了一個ServerSocket類智嚷,該類的實(shí)例對象可以實(shí)現(xiàn)一個服務(wù)器段的程序卖丸。通過查閱API文檔可知,ServerSocket類提供了多種構(gòu)造方法盏道,接下來就對ServerSocket的構(gòu)造方法進(jìn)行逐一地講解稍浆。


構(gòu)造方法.png

使用該構(gòu)造方法在創(chuàng)建ServerSocket對象時,就可以將其綁定到一個指定的端口號上(參數(shù)port就是端口號)猜嘱。
接下來學(xué)習(xí)一下ServerSocket的常用方法衅枫,如表所示。


常用方法.png

ServerSocket對象負(fù)責(zé)監(jiān)聽某臺計(jì)算機(jī)的某個端口號朗伶,在創(chuàng)建ServerSocket對象后弦撩,需要繼續(xù)調(diào)用該對象的accept()方法,接收來自客戶端的請求论皆。當(dāng)執(zhí)行了accept()方法之后益楼,服務(wù)器端程序會發(fā)生阻塞,直到客戶端發(fā)出連接請求点晴,accept()方法才會返回一個Scoket對象用于和客戶端實(shí)現(xiàn)通信感凤,程序才能繼續(xù)向下執(zhí)行。
  • Socket
  • 講解了ServerSocket對象可以實(shí)現(xiàn)服務(wù)端程序粒督,但只實(shí)現(xiàn)服務(wù)器端程序還不能完成通信陪竿,此時還需要一個客戶端程序與之交互,為此JDK提供了一個Socket類坠陈,用于實(shí)現(xiàn)TCP客戶端程序萨惑。
    通過查閱API文檔可知Socket類同樣提供了多種構(gòu)造方法,接下來就對Socket的常用構(gòu)造方法進(jìn)行詳細(xì)講解仇矾。


    構(gòu)造方法.png

    使用該構(gòu)造方法在創(chuàng)建Socket對象時庸蔼,會根據(jù)參數(shù)去連接在指定地址和端口上運(yùn)行的服務(wù)器程序,其中參數(shù)host接收的是一個字符串類型的IP地址贮匕。


    構(gòu)造方法.png

    該方法在使用上與第二個構(gòu)造方法類似姐仅,參數(shù)address用于接收一個InetAddress類型的對象,該對象用于封裝一個IP地址刻盐。
    在以上Socket的構(gòu)造方法中掏膏,最常用的是第一個構(gòu)造方法。
  • 接下來學(xué)習(xí)一下Socket的常用方法敦锌,如表所示


    常用方法.png

    在Socket類的常用方法中馒疹,getInputStream()和getOutStream()方法分別用于獲取輸入流和輸出流。當(dāng)客戶端和服務(wù)端建立連接后乙墙,數(shù)據(jù)是以IO流的形式進(jìn)行交互的颖变,從而實(shí)現(xiàn)通信生均。

  • 接下來通過一張圖來描述服務(wù)器端和客戶端的數(shù)據(jù)傳輸,如下圖所示腥刹。


    數(shù)據(jù)傳輸.png
  • TCP協(xié)議實(shí)現(xiàn)
  • 案例代碼三:
package com.neuedu.demo;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/*
* 使用TCP協(xié)議發(fā)送數(shù)據(jù)
*     創(chuàng)建發(fā)送端Socket對象(創(chuàng)建連接)
*     獲取輸出流對象
*     發(fā)送數(shù)據(jù)
*     釋放資源
*     
* Socket(InetAddress address, int port) 
* Exception in thread "main" java.net.ConnectException: Connection refused: connect
*
*/
public class ClientDemo {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建發(fā)送端Socket對象(創(chuàng)建連接)
      Socket s = new Socket(InetAddress.getByName("itheima"),10086);
      //獲取輸出流對象
      OutputStream os = s.getOutputStream();
      //發(fā)送數(shù)據(jù)
      String str = "hello tcp,im comming!!!";
      os.write(str.getBytes());
      //釋放資源
      //os.close();
      s.close();
  }
}
package com.neuedu.demo;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/*
* 使用TCP協(xié)議接收數(shù)據(jù)
*         創(chuàng)建接收端Socket對象
*         監(jiān)聽(阻塞)
*         獲取輸入流對象
*         獲取數(shù)據(jù)
*         輸出數(shù)據(jù)
*         釋放資源
*     
* ServerSocket:接收端马胧,服務(wù)端Socket
*     ServerSocket(int port) 
* Socket accept() 
* 
*/
public class ServerDemo {
  public static void main(String[] args) throws IOException  {
      //創(chuàng)建接收端Socket對象
      ServerSocket ss = new ServerSocket(10086);
      //監(jiān)聽(阻塞)
      Socket s = ss.accept();
      //獲取輸入流對象
      InputStream is = s.getInputStream();
      //獲取數(shù)據(jù)
      byte[] bys = new byte[1024];
      int len;//用于存儲讀到的字節(jié)個數(shù)
      len = is.read(bys);
      //輸出數(shù)據(jù)
      InetAddress address = s.getInetAddress();
      System.out.println("client ---> " + address.getHostName());
      System.out.println(new String(bys,0,len));
      //釋放資源
      s.close();
      //ss.close();
  }
}
  • TCP相關(guān)案例
  • 案例代碼四:
    使用TCP協(xié)議發(fā)送數(shù)據(jù),服務(wù)端將接收到的數(shù)據(jù)轉(zhuǎn)換成大寫返回給客戶端
package com.neuedu.demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/*
*     需求:使用TCP協(xié)議發(fā)送數(shù)據(jù)衔峰,并將接收到的數(shù)據(jù)轉(zhuǎn)換成大寫返回
*     
*     客戶端發(fā)出數(shù)據(jù)
*     服務(wù)端接收數(shù)據(jù)
*     服務(wù)端轉(zhuǎn)換數(shù)據(jù)
*     服務(wù)端發(fā)出數(shù)據(jù)
*     客戶端接收數(shù)據(jù)
* 
*/
public class ClientDemo {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建客戶端Socket對象
      Socket s = new Socket(InetAddress.getByName("itheima"),10010);
      //獲取輸出流對象
      OutputStream os = s.getOutputStream();
      //發(fā)出數(shù)據(jù)
      os.write("tcp,im comming again!!!".getBytes());

      
      //獲取輸入流對象
      InputStream is = s.getInputStream();
      byte[] bys = new byte[1024];
      int len;//用于存儲讀取到的字節(jié)個數(shù)
      //接收數(shù)據(jù)
      len = is.read(bys);
      //輸出數(shù)據(jù)
      System.out.println(new String(bys,0,len));
      
      //釋放資源
      s.close();
      
  }
}
package com.neuedu.demo;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建服務(wù)端Socket對象
      ServerSocket ss = new ServerSocket(10010);
      //監(jiān)聽
      Socket s = ss.accept();
      //獲取輸入流對象
      InputStream is = s.getInputStream();
      //獲取數(shù)據(jù)
      byte[] bys = new byte[1024];
      int len;//用于存儲讀取到的字節(jié)個數(shù)
      len = is.read(bys);
      String str = new String(bys,0,len);
      //輸出數(shù)據(jù)
      System.out.println(str);
      //轉(zhuǎn)換數(shù)據(jù)
      String upperStr = str.toUpperCase();
      //獲取輸出流對象
      OutputStream os = s.getOutputStream();
      //返回數(shù)據(jù)(發(fā)出數(shù)據(jù))
      os.write(upperStr.getBytes());
      
      //釋放資源
      s.close();
      //ss.close();//服務(wù)端一般不關(guān)閉
  }
}
  • 案例代碼五:
  • 客戶端:
    1.提示用戶輸入用戶名和密碼,將用戶輸入的用戶名和密碼發(fā)送給服務(wù)端
    2.接收服務(wù)端驗(yàn)證完用戶名和密碼的結(jié)果
  • 服務(wù)端:
    1.接收客戶端發(fā)送過來的用戶名和密碼
    2.如果用戶名不是itheima或者 密碼不是123456,就向客戶端寫入”登錄失敗”
    否則向客戶端寫入登錄成功
package com.neuedu.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/*
* 模擬用戶登錄
*/
public class ClientTest {
  public static void main(String[] args) throws  IOException  {
      //創(chuàng)建客戶端Socket對象
      //Socket s = new Socket(InetAddress.getByName("itheima"),8888);
      Socket s = new Socket("itheima",8888);
      
      //獲取用戶名和密碼
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      System.out.println("請輸入用戶名:");
      String username = br.readLine();
      System.out.println("請輸入密碼:");
      String password = br.readLine();
      
      
      //獲取輸出流對象
      //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
      //寫出數(shù)據(jù)
      out.println(username);
      out.println(password);
      
      //獲取輸入流對象
      BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream()));
      //獲取服務(wù)器返回的數(shù)據(jù)
      String result = serverBr.readLine();
      System.out.println(result);
      //釋放資源
      s.close();
  }
}
package com.neuedu.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建服務(wù)器端Socket對象
      ServerSocket ss = new ServerSocket(8888);
      //監(jiān)聽
      Socket s = ss.accept();
      //獲取輸入流對象
      BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
      //獲取用戶名和密碼
      String username = br.readLine();
      String password = br.readLine();
      //判斷用戶名和密碼是否正確
      boolean flag = false;
      if("itheima".equals(username) && "123456".equals(password)) {
          flag = true;
      }
      //獲取輸出流對象
      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
      
      //返回判斷信息
      if(flag) {
          out.println("登陸成功");
      }
      else {
          out.println("登陸失敗");
      }
      //釋放資源
      s.close();
      //ss.close();//服務(wù)器一般不關(guān)閉
  }
}
  • 案例代碼六:
  • 將用戶名和密碼封裝到一個User類中,提供對應(yīng)的構(gòu)造方法和getter/setter方法
  • 新建一個UserDB類里面定義一個集合,在集合中添加以下User對象
    new User("zhangsan","123456");
    new User("lisi","654321");
    new User("itheima","itheima");
    new User("admin","password");
  • 客戶端:
    1.提示用戶輸入用戶名和密碼,將用戶輸入的用戶名和密碼發(fā)送給服務(wù)端
    2.接收服務(wù)端驗(yàn)證完用戶名和密碼的結(jié)果
  • 服務(wù)端:
  1. 服務(wù)端將客戶端發(fā)送過來的用戶名密碼封裝成User對象
  2. 集合中如果包括這個User對象,想客戶端寫入” 登錄成功”
    否則向客戶端寫入”登錄失敗”
package com.neuedu.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/*
* 模擬用戶登錄改寫(面向?qū)ο蟀姹荆?*/
public class ClientTest {
  public static void main(String[] args) throws  IOException  {
      //創(chuàng)建客戶端Socket對象
      Socket s = new Socket("itheima",8888);
      
      //獲取用戶名和密碼
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      System.out.println("請輸入用戶名:");
      String username = br.readLine();
      System.out.println("請輸入密碼:");
      String password = br.readLine();
      
      
      //獲取輸出流對象
      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
      //寫出數(shù)據(jù)
      out.println(username);
      out.println(password);
      
      //獲取輸入流對象
      BufferedReader serverBr = new BufferedReader(new InputStreamReader(s.getInputStream()));
      //獲取服務(wù)器返回的數(shù)據(jù)
      String result = serverBr.readLine();
      System.out.println(result);
      //釋放資源
      s.close();
  }
}
package com.neuedu.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;

public class ServerTest {
  public static void main(String[] args) throws IOException {
      //創(chuàng)建服務(wù)器端Socket對象
      ServerSocket ss = new ServerSocket(8888);
      //監(jiān)聽
      Socket s = ss.accept();
      //獲取輸入流對象
      BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
      //獲取用戶名和密碼
      String username = br.readLine();
      String password = br.readLine();
      //判斷用戶名和密碼是否正確
      boolean flag = false;
  
      /*if("itheima".equals(username) && "123456".equals(password)) {
          flag = true;
      }*/
      
      List<User> users = UserDB.getUsers();
      User user = new User(username,password);
      if(users.contains(user)) {
          //匹配成功
          flag = true;
      }
      
      
      //獲取輸出流對象
      PrintWriter out = new PrintWriter(s.getOutputStream(),true);
      
      //返回判斷信息
      if(flag) {
          out.println("登陸成功");
      }
      else {
          out.println("登陸失敗");
      }
      //釋放資源
      s.close();
      //ss.close();//服務(wù)器一般不關(guān)閉
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末佩脊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子垫卤,更是在濱河造成了極大的恐慌威彰,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葫男,死亡現(xiàn)場離奇詭異抱冷,居然都是意外死亡崔列,警方通過查閱死者的電腦和手機(jī)梢褐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赵讯,“玉大人盈咳,你說我怎么就攤上這事”咭恚” “怎么了鱼响?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長组底。 經(jīng)常有香客問我丈积,道長,這世上最難降的妖魔是什么债鸡? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任江滨,我火速辦了婚禮,結(jié)果婚禮上厌均,老公的妹妹穿的比我還像新娘唬滑。我一直安慰自己,他們只是感情好棺弊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布晶密。 她就那樣靜靜地躺著,像睡著了一般模她。 火紅的嫁衣襯著肌膚如雪稻艰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天侈净,我揣著相機(jī)與錄音尊勿,去河邊找鬼归苍。 笑死,一個胖子當(dāng)著我的面吹牛运怖,可吹牛的內(nèi)容都是我干的拼弃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼摇展,長吁一口氣:“原來是場噩夢啊……” “哼吻氧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咏连,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤盯孙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祟滴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體振惰,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年垄懂,在試婚紗的時候發(fā)現(xiàn)自己被綠了骑晶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡草慧,死狀恐怖桶蛔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漫谷,我是刑警寧澤仔雷,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站舔示,受9級特大地震影響碟婆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惕稻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一竖共、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缩宜,春花似錦肘迎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宋梧,卻和暖如春匣沼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捂龄。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工释涛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留加叁,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓唇撬,卻偏偏與公主長得像它匕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窖认,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 7.2 面向套接字編程我們已經(jīng)通過了解Socket的接口豫柬,知其所以然,下面我們就將通過具體的案例扑浸,來熟悉Socke...
    lucas777閱讀 1,173評論 0 2
  • 計(jì)算機(jī)網(wǎng)絡(luò)概述 網(wǎng)絡(luò)編程的實(shí)質(zhì)就是兩個(或多個)設(shè)備(例如計(jì)算機(jī))之間的數(shù)據(jù)傳輸烧给。 按照計(jì)算機(jī)網(wǎng)絡(luò)的定義,通過一定...
    蛋炒飯_By閱讀 1,215評論 0 10
  • 一喝噪、基礎(chǔ)知識:1础嫡、JVM、JRE和JDK的區(qū)別:JVM(Java Virtual Machine):java虛擬機(jī)...
    殺小賊閱讀 2,369評論 0 4
  • package net; import java.io.BufferedReader; import java.i...
    自由主義者閱讀 528評論 0 0
  • 賬號分類與標(biāo)的 一酝惧、企業(yè)號: 企業(yè)官網(wǎng)展示功能 二榴鼎、個人號: 1、目標(biāo)成為領(lǐng)域?qū)<姨栂捣睢⑼癸@人文特點(diǎn)檬贰,按照一個資深真...
    HaloMark閱讀 24,264評論 0 1