JAVA學(xué)習(xí)筆記06——網(wǎng)絡(luò)編程基礎(chǔ)

JAVA學(xué)習(xí)筆記06——網(wǎng)絡(luò)編程基礎(chǔ)

網(wǎng)絡(luò)相關(guān)概念

  • 網(wǎng)絡(luò)通信

    • 概念:兩臺(tái)設(shè)備之間通過網(wǎng)絡(luò)實(shí)現(xiàn)數(shù)據(jù)傳輸
    • 網(wǎng)絡(luò)通信:將數(shù)據(jù)通過網(wǎng)絡(luò)從一臺(tái)設(shè)備傳輸?shù)搅硪慌_(tái)設(shè)備
    • Java.net包下提供了一系列的類或接口,供程序員使用崇棠,完成網(wǎng)絡(luò)通信
  • 網(wǎng)絡(luò):

    • 概念:兩臺(tái)或多臺(tái)設(shè)備通過一定物理設(shè)備連接起來構(gòu)成了網(wǎng)絡(luò)
    • 根據(jù)網(wǎng)絡(luò)的覆蓋范圍不同毡咏,對(duì)網(wǎng)絡(luò)進(jìn)行分類:
      • 局域網(wǎng)
      • 城域網(wǎng)
      • 廣域網(wǎng)
  • ip地址:

    • 概念:用于唯一標(biāo)識(shí)網(wǎng)絡(luò)中的每臺(tái)計(jì)算機(jī)/主機(jī)

    • 查看ip地址:ipconfig

    • ip表示:

      • 點(diǎn)分十進(jìn)制

      • 對(duì)于IPv4用4個(gè)字節(jié)(32位)表示

      0~255 0~255 0~255 0~255
    • ip地址的組成=網(wǎng)絡(luò)地址+主機(jī)地址锭吨,比如:192.168.1.1

    • IPv6是互聯(lián)網(wǎng)工程任務(wù)組設(shè)計(jì)的用于替代IPv4的下一代IP協(xié)議

    • IPv4地址分類:

      • A類:0.0.0.0到127.255.255.255
      • B類:128.0.0.0到191.255.255.255
      • C類:192.0.0.0到223.255.255.255
      • D類:224.0.0.0到239.255.255.255
      • E類:240.0.0.0到247.255.255.255

域名和端口

域名

  • 例如:www.baidu.com
  • 好處:為了方便記憶离赫,解決記IP地址困難的問題
  • 概念:將IP地址映射成域名事富,HTTP協(xié)議

端口號(hào)

  • 概念:用于標(biāo)識(shí)計(jì)算機(jī)上某個(gè)特定的網(wǎng)絡(luò)程序
  • 表示形式:以整數(shù)形式梨与,范圍0~65535
  • 0~1024已經(jīng)被占用捡硅,比如ssh 22秉继,ftp 21祈噪,smtp 25,http 80
  • 常見的網(wǎng)絡(luò)程序端口號(hào):
    • tomcat 8080
    • mysql 3306
    • oracle 1521
    • sqlserver:1433

網(wǎng)絡(luò)協(xié)議

  • 協(xié)議是網(wǎng)絡(luò)編程中數(shù)據(jù)的組織形式

  • OSI模型(理論) TCP/IP模型 TCP/IP模型各層對(duì)應(yīng)協(xié)議
    應(yīng)用層 應(yīng)用層 HTTP尚辑、ftp辑鲤、telnet、DNS……
    表示層
    會(huì)話層
    傳輸層 傳輸層(TCP) TCP杠茬、UDP……
    網(wǎng)絡(luò)層 網(wǎng)絡(luò)層(IP) IP月褥、ICMP、ARP……
    數(shù)據(jù)鏈路層 物理+數(shù)據(jù)鏈路層 Link
    物理層

TCP和UDP

  • TCP傳輸控制協(xié)議
    • TCP/IP(Transmission Control Protocol/Internet Protocol)的簡寫澈蝙。
    • 中文譯名為傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議吓坚,又叫網(wǎng)絡(luò)通訊協(xié)議,這個(gè)協(xié)議是Internet最基本的協(xié)議灯荧,簡單地說礁击,就是由網(wǎng)絡(luò)層的IP協(xié)議和傳輸層的TCP協(xié)議組成的
    • 使用TCP協(xié)議前,須先建立TCP連接逗载,形成傳輸數(shù)據(jù)通道
    • 傳輸前哆窿,采用”三次握手“方式,是可靠的
    • TCP協(xié)議進(jìn)行通信的兩個(gè)應(yīng)用進(jìn)程:客戶端厉斟、服務(wù)端
    • 在連接中可進(jìn)行大數(shù)據(jù)量的傳輸
    • 傳輸完畢挚躯,需釋放已建立連接,效率低
  • UDP協(xié)議
    • 將數(shù)據(jù)擦秽、源码荔、目的封裝成數(shù)據(jù)包漩勤,不需要建立連接
    • 每個(gè)數(shù)據(jù)包的大小限制在64K以內(nèi),不適合傳輸大量數(shù)據(jù)
    • 因無需連接缩搅,所以是不可靠的
    • 發(fā)送數(shù)據(jù)結(jié)束時(shí)無需釋放資源(因?yàn)椴皇敲嫦蜻B接的)越败,速度快

InetAddress類

相關(guān)方法

  • 獲取本機(jī)InetAddress對(duì)象getLocalHost
  • 根據(jù)指定主機(jī)名、域名獲取ip地址對(duì)象getByName
  • 獲取InetAddress對(duì)象的主機(jī)名getHostName
  • 獲取InetAddress對(duì)象的地址getHostAddress
import java.net.InetAddress;
import java.net.UnknownHostException;

public class API {
    public static void main(String[] args) throws UnknownHostException {
        // 獲取本機(jī)的InetAddress對(duì)象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);

        // 根據(jù)指定主機(jī)名獲取InetAddress對(duì)象
        InetAddress host1 = InetAddress.getByName("DESKTOP-CQHA3I8");
        System.out.println("host1 = " + localHost);

        // 根據(jù)域名返回InetAddress對(duì)象
        InetAddress  host2 = InetAddress.getByName("www.baidu.com");
        System.out.println("host2 = " + host2);

        // 通過InetAddress對(duì)象硼瓣,獲取對(duì)應(yīng)的地址
        String host2Address = host2.getHostAddress();
        System.out.println("host2地址:" + host2Address);

        // 通過InetAddress對(duì)象究飞,獲得主機(jī)名或域名
        String host2Name = host2.getHostName();
        System.out.println("host2主機(jī)名/域名:" + host2Name);
    }
}

Socket

  • 基本介紹:
    • 套接字(Socket)開發(fā)網(wǎng)絡(luò)應(yīng)用程序被廣泛采用,以至于成為事實(shí)上的標(biāo)準(zhǔn)
    • 通信的兩端都要由Socket堂鲤,是兩臺(tái)機(jī)器間通信的端點(diǎn)
    • 網(wǎng)絡(luò)通信其實(shí)就是Socket間的通信
    • Socket允許把網(wǎng)絡(luò)連接當(dāng)成一個(gè)流亿傅,數(shù)據(jù)在兩個(gè)Socket間通過IO傳輸。
    • 一般主動(dòng)發(fā)起通信的應(yīng)用程序?qū)倏蛻舳宋疗埽却ㄐ耪?qǐng)求的為服務(wù)端
    • 當(dāng)我們需要通訊時(shí)(讀寫數(shù)據(jù))
      • socket.getOutputStream()
      • socket.getInputStream()
    • Socket有TCP編程和UDP編程

TCP網(wǎng)絡(luò)通信編程

  • 基本介紹

    • 基于客戶端—服務(wù)端的網(wǎng)絡(luò)通信
    • 底層使用的時(shí)TCP/IP協(xié)議
    • 應(yīng)用場景舉例:客戶端發(fā)送數(shù)據(jù)葵擎,服務(wù)端接受并顯示
    • 基于Socket的TCP編程
  • 案例:

    // 服務(wù)端
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketServer {
        public static void main(String[] args) throws IOException {
            // 在9999接口監(jiān)聽,等待連接
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("等待連接……");
            // 當(dāng)沒有客戶端連接時(shí)慢宗,程序阻塞坪蚁,等待連接
            Socket socket = serverSocket.accept();
            System.out.println("服務(wù)端 socket = " + socket.getClass());
            // 讀取客戶端寫入數(shù)據(jù)通道的數(shù)據(jù)
            InputStream inputStream = socket.getInputStream();
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = inputStream.read(buf)) != -1) {
                System.out.println(new String(buf, 0, readLen));
            }
            // 關(guān)閉流和socket
            inputStream.close();
            socket.close();
        }
    }
    
    // 客戶端
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.nio.charset.StandardCharsets;
    
    public class SocketTCPClient {
        public static void main(String[] args) throws IOException {
            // 連接服務(wù)器,如果連接成功镜沽,返回Socket對(duì)象
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            System.out.println("客戶端 socket = " + socket.getClass());
            // 連接上后,生成Socket,通過socket.getOutputStream()得到和Socket對(duì)象關(guān)聯(lián)的輸出流對(duì)象
            OutputStream outputStream = socket.getOutputStream();
    
            outputStream.write("hello server".getBytes(StandardCharsets.UTF_8));
            socket.shutdownOutput();
            // 關(guān)閉流和Socket對(duì)象贱田,必須關(guān)閉
            outputStream.close();
            socket.close();
            System.out.println("Socket關(guān)閉");
        }
    }
    
  • 應(yīng)該設(shè)置一個(gè)結(jié)束標(biāo)記缅茉,說明結(jié)束發(fā)送數(shù)據(jù)。socket.shutdownOutput()

  • 案例男摧,網(wǎng)絡(luò)上傳文件

    // 服務(wù)端
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPFileCopyServer {
        public static void main(String[] args) throws IOException {
            // 1.服務(wù)端在本機(jī)8888端口監(jiān)聽
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("服務(wù)端在8888");
            // 2.等待連接
            Socket socket = serverSocket.accept();
            // 3.讀取客戶端發(fā)送的數(shù)據(jù)
            //   通過socket得到輸入流
            BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
            ByteArrayOutputStream bos = new ByteArrayOutputStream();// 創(chuàng)建輸出流對(duì)象
            byte[] b = new byte[1024];// 字節(jié)數(shù)組
            int len;
            while ((len = bufferedInputStream.read(b)) != -1) {// 循環(huán)讀取
                bos.write(b, 0, len);// 把讀取到的數(shù)據(jù)寫入bos
            }
            byte[] array = bos.toByteArray();// 然后將bos 轉(zhuǎn)成字節(jié)數(shù)組
            bos.close();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\Users\\46429\\Pictures\\qie233.GIF"));
            bufferedOutputStream.write(array);
            bufferedOutputStream.close();
            bufferedInputStream.close();
            
            socket.close();
            serverSocket.close();
        }
    }
    
    // 客戶端
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPFileCopyClient {
        public static void main(String[] args) throws IOException {
    
            // 客戶端連接服務(wù)端蔬墩,得到Socket對(duì)象
            Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
            // 創(chuàng)建讀取磁盤文件的輸入流
            String filePath = "C:\\Users\\46429\\Pictures\\qie.GIF";
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream bos = new ByteArrayOutputStream();// 創(chuàng)建輸出流對(duì)象
            byte[] b = new byte[1024];// 字節(jié)數(shù)組
            int len;
            while ((len = bufferedInputStream.read(b)) != -1) {// 循環(huán)讀取
                bos.write(b, 0, len);// 把讀取到的數(shù)據(jù)寫入bos
            }
            byte[] array = bos.toByteArray();// 然后將bos 轉(zhuǎn)成字節(jié)數(shù)組
            bos.close();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
            bufferedOutputStream.write(array);
            bufferedInputStream.close();
            bufferedOutputStream.close();
            socket.shutdownOutput();
        }
    }
    

netstat指令

  • netstat -an 可以查看當(dāng)前主機(jī)網(wǎng)絡(luò)情況,包括端口監(jiān)聽情況和網(wǎng)絡(luò)連接情況

  • netstat -an|more可以分頁顯示

  • 要求在dos控制臺(tái)下執(zhí)行win + r

  • netstat.png
  • 說明:

    • Listening表示某個(gè)端口在監(jiān)聽
    • 如果有一個(gè)外部程序(客戶端)連接到該端口耗拓,就會(huì)顯示一條連接信息
    • 可以輸入ctrl+c退出指令
  • netstat -anb 查看使用端口的程序拇颅,需要使用管理員權(quán)限

TCP注意點(diǎn)

  • 客戶端連接到服務(wù)器端后,實(shí)際上客戶端也是通過一個(gè)端口和服務(wù)端進(jìn)行通訊的乔询,這個(gè)端口時(shí)TCP/IP來分配的樟插,是隨機(jī)的。

UDP網(wǎng)絡(luò)編程

基本介紹

  • 類DatagramSocket和DatagramPacket(數(shù)據(jù)包/數(shù)據(jù)報(bào))實(shí)現(xiàn)了基于UDP協(xié)議網(wǎng)絡(luò)程序
  • UDP數(shù)據(jù)報(bào)通過數(shù)據(jù)報(bào)(數(shù)據(jù)包)套接字DatagramSocket發(fā)送和接收竿刁,系統(tǒng)不保證UDP數(shù)據(jù)報(bào)一定能夠安全送達(dá)目的地黄锤,也不能確定什么時(shí)候可以抵達(dá)。
  • DatagramPacket對(duì)象封裝了UDP數(shù)據(jù)報(bào)食拜,在數(shù)據(jù)報(bào)中包含了發(fā)送端的IP地址和端口號(hào)以及接受端的IP地址和端口號(hào)
  • UDP協(xié)議中每個(gè)數(shù)據(jù)報(bào)都給出了完整的地址信息鸵熟,因此無需建立發(fā)送方和接收方的連接

UDP網(wǎng)絡(luò)編程基礎(chǔ)流程

  • 核心的兩個(gè)類/對(duì)象DatagramSocket與DatagramPacket
  • 建立發(fā)送端,接收端
  • 建立數(shù)據(jù)包
  • 調(diào)用DatagramSocket的發(fā)送负甸、接受方法
  • 關(guān)閉DatagramSocket

UDP說明

  • 沒有明確的服務(wù)端和客戶端流强,演變成數(shù)據(jù)的發(fā)送端和接收端
  • 接收數(shù)據(jù)和發(fā)送數(shù)據(jù)是通過DatagramSocket對(duì)象完成
  • 將數(shù)據(jù)封裝到DatagramPacket對(duì)象/裝包
  • 當(dāng)接受到DatagramPacket對(duì)象痹届,需要進(jìn)行拆包,取出數(shù)據(jù)
  • DatagramSocket可以指定在哪個(gè)端口接收數(shù)據(jù)

應(yīng)用案例

  • 編寫一個(gè)接收端A打月,和一個(gè)發(fā)送端B
  • 接收端A在9999端口等待接受數(shù)據(jù)(receive)
  • 發(fā)送端B向接收端A發(fā)送數(shù)據(jù)“hello队腐,明天吃火鍋”
  • 接收端A接收到發(fā)送端B發(fā)送的數(shù)據(jù),回復(fù)“好的僵控,明天見”再退出
  • 發(fā)送端接收回復(fù)的數(shù)據(jù)香到,再退出
// 接收端A
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        // 創(chuàng)建一個(gè)DatagramSocket對(duì)象,準(zhǔn)備接受數(shù)據(jù)
        DatagramSocket socket = new DatagramSocket(9999);
        byte[] buf = new byte[1024];// 一個(gè)數(shù)據(jù)包最大64k
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        // 調(diào)用接收方法
        System.out.println("接收端A接受數(shù)據(jù)报破。悠就。。");
        socket.receive(packet);

        int length = packet.getLength();
        byte[] data = packet.getData();
        String s = new String(data, 0, length);
        System.out.println(s);

        byte[] response = "彳亍".getBytes(StandardCharsets.UTF_8);
        DatagramPacket rPacket = new DatagramPacket(response, response.length, InetAddress.getByName("172.25.225.69"), 9998);
        socket.send(rPacket);
        // 關(guān)閉資源
        socket.close();
        System.out.println("A端退出");
    }
}
// 發(fā)送端B
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

public class UDPSenderB {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(9998);
        // 將發(fā)送的數(shù)據(jù)封裝到packet對(duì)象
        byte[] data = "明天吃火鍋3湟住9Fⅰ!".getBytes(StandardCharsets.UTF_8);
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("172.25.225.69"), 9999);
        socket.send(packet);

        byte[] response = new byte[1024];
        DatagramPacket rPacket = new DatagramPacket(response,response.length);
        System.out.println("接收A端數(shù)據(jù)盹靴。炸茧。。");
        socket.receive(rPacket);
        byte[] bRe = rPacket.getData();
        String re = new String(bRe, 0,rPacket.getLength());
        System.out.println(re);
        System.out.println("ok");

        socket.close();
        System.out.println("B端退出");
    }
}

個(gè)人總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市改备,隨后出現(xiàn)的幾起案子控漠,更是在濱河造成了極大的恐慌,老刑警劉巖悬钳,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盐捷,死亡現(xiàn)場離奇詭異,居然都是意外死亡默勾,警方通過查閱死者的電腦和手機(jī)碉渡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來母剥,“玉大人滞诺,你說我怎么就攤上這事∠碧拢” “怎么了铭段?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秦爆。 經(jīng)常有香客問我序愚,道長,這世上最難降的妖魔是什么等限? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任爸吮,我火速辦了婚禮芬膝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘形娇。我一直安慰自己锰霜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布桐早。 她就那樣靜靜地躺著癣缅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哄酝。 梳的紋絲不亂的頭發(fā)上友存,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音陶衅,去河邊找鬼屡立。 笑死,一個(gè)胖子當(dāng)著我的面吹牛搀军,可吹牛的內(nèi)容都是我干的膨俐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼罩句,長吁一口氣:“原來是場噩夢啊……” “哼焚刺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起门烂,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤檩坚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后诅福,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拖叙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年氓润,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薯鳍。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咖气,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挖滤,到底是詐尸還是另有隱情崩溪,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布斩松,位于F島的核電站伶唯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惧盹。R本人自食惡果不足惜乳幸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一瞪讼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粹断,春花似錦符欠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至养筒,卻和暖如春曾撤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闽颇。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國打工盾戴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兵多。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓尖啡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親剩膘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衅斩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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