计算机网络编程实战

1. 概述

image-20210219103136475
  • TCP传输控制协议Transmission Control Protocol)
  • UDP用户数据报协议User Datagram Protocol)

计算机网络:计算机网络是指将==地理位置不同的具有独立功能的多台计算机及其外部设备==,通过通信线路连接起来,在网络操作系统网络管理软件及==网络通信协议==的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程的目的:无线电台,传播交流信息,数据交换,通信。

  • javaweb:网页编程 B/S (Browser/Server)
  • 网络编程:TCP/IP C/S (Client/Server)

2. 网络通信的要素

网络通信的要素

  1. 通信双方地址

    • ip:互联网协议地址(Internet Protocol Access)
    • port:端口号
  2. 网络通信协议

    • TCP,UDP

TCP/IP 参考模型(也叫OSI七层模型):

img

OSI详解1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PIV42Y1v-1613961352614)(…/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/OSI%E8%AF%A6%E8%A7%A32.png)]

OSI详解3

参考:图解OSI七层模型OSI七层模型详解

image-20210219112002893

3. IP

ip在java中位置:java.net.InetAddress

  • ip用于定位一台计算机(唯一地址)

  • 127.0.0.1:本机地址

  • ip地址分类

    • ipv4/ipv6(internet protocol version 4/6)

      • ipv4,eg:127.0.0.1,总长度为32bit(4Byte),分为4组,每组为一个0~255的数,每组用冒汗分隔,共43亿个;30亿在北美,亚洲只有4亿个,2011年用尽
      • ipv6,eg:fe80::2912:6519:9f57:3c64%2,总长度为128bit(16Byte),分为8组,每组为4个十六进制数,每组十六进制数间用冒号分隔,拥有(43亿×43亿×43亿×43亿)个地址
      • 在某些情况下,一个IPv6地址中间可能包含很长的一段0,可以把连续的一段0压缩为“::”。但为保证地址解析的唯一性,地址中”::”只能出现一次,例如:
          FF01:0:0:0:0:0:0:1101 → FF01::1101
          0:0:0:0:0:0:0:1 → ::1
          0:0:0:0:0:0:0:0 → ::
    • 公网(互联网)- 私网(局域网)

      • ABCDE类地址20200711100900871
    • 域名(Domain Name)

      • eg:www.baidu.com
      • 由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址
public class TestInetAddress {
    public static void main(String[] args) {
        try {
            // 获取本地的ip地址
            InetAddress localAddress1 = InetAddress.getByName("127.0.0.1");
            System.out.println(localAddress1);
            // 获取本地的ip地址
            InetAddress localAddress2 = InetAddress.getByName("localhost");
            System.out.println(localAddress2);
            // 获取本地的ip地址
            InetAddress localAddress3 = InetAddress.getLocalHost();
            System.out.println(localAddress3);

            // 获取百度的ip地址
            InetAddress baiduAddress = InetAddress.getByName("www.baidu.com");
            System.out.println(baiduAddress);

            // 常用方法
            // 返回该对象的Byte类型的 InetAddress原IP地址
            System.out.println(baiduAddress.getAddress());
            // 返回String类型的 IP地址
            System.out.println(baiduAddress.getHostAddress());
             // 返回此IP地址的 完全限定的域名
            System.out.println(baiduAddress.getCanonicalHostName());
            // 返回此IP地址的 主机名
            System.out.println(baiduAddress.getHostName());                 
            
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
image-20210219161522478

4. Port

  • 端口(Port):一般是指TCP/IP协议中的端口,

  • 端口分为两种,一种是TCP端口,一种是UDP端口。计算机之间相互通信的时候,分为两种方式:一种是发送信息以后,可以确认信息是否到达,也就是有应答的方式,这种方式大多采用TCP协议;一种是发送以后就不管了,不去确认信息是否到达,这种方式大多采用UDP协议。对应这两种协议的服务提供的端口,也就分为TCP端口和UDP端口。

  • 端口号的范围从0到65535,TCP端口有65536个,UDP端口也有65536个,单个协议下,端口号不能冲突

  • 端口分类

    • 公用端口:0~1023

      • FTP:21
      • Telnet:23
      • HTTP:80
      • HTTPS:443
    • 程序注册端口:1024~49151,分配用户or程序

      • Oracle:1521
      • MySQL:3306
      • Tomcat:8080
    • 动态、私有:49152~65535

      netstat -ano				# 查看所有端口 
      netstat -ano|findstr "443"		# 查看指定端口号(443)
      tasklist|findstr "12252"		# 查看指定端口进程(12252)
      
    • InetSocketAddress

public static void main(String[] args) {
    InetSocketAddress localSocketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
    System.out.println(localSocketAddress1);

    InetSocketAddress localSocketAddress2 = new InetSocketAddress("localhost", 8080);
    System.out.println(localSocketAddress2);
	
    // 获得InetAddress
    System.out.println(localSocketAddress1.getAddress());
    // 获得hostname(主机名)
    System.out.println(localSocketAddress1.getHostName());
    // 获得hostname(主机名),和上面效果一样
    System.out.println(localSocketAddress1.getHostString());
    // 获得端口号
    System.out.println(localSocketAddress1.getPort());
}
image-20210220093010677
  • 修改host

    • host文件地址:C:\Windows\System32\drivers\etc\hosts
    • host右键属性->去掉只读上的点
    • 打开修改

5. 通信协议

5.1 TCP与UDP的区别

5.1.1 TCP:打电话

  • 连接,稳定,传输完成,释放连接,效率低

  • 三次握手three-way handshake):至少需要三次,保证稳定连接

    A:你愁啥?
    B:瞅你咋地?
    A:干一场!
    
  • 四次挥手(four-way wavehand)

    A:我要走了!
    B:你真的要走了吗?
    B:你真的真的要走了吗?
    A:我真的真的要走了!
    

    先简单了解,到时候看书

  • 分为客户端与服务端

5.1.2 UDP:发短信

  • 不连接,不稳定,不管有没有准备好,都可以发给你
  • 客户端、服务端:没有明确的界限
  • DDoS:洪水攻击!(饱和攻击)

5.2 TCP发送消息

  • 服务器端:

    1. 创建服务器端口 new ServerSocket()

      ServerSocket serverSocket = new ServerSocket(9999);
      
    2. 阻塞式监听,会一直等待客户端连接 serverSocket.accept()

      Socket socket = serverSocket.accept();
      
    3. 读取客户端消息 socket.getInputStream()

      InputStream is = socket.getInputStream();
      
    4. 解析socket数据

      ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
      byte[] buffer = new byte[1024];
      int len = 0;
      while((len = is.read(buffer)) != -1) {
          baoStream.write(buffer, 0, len);
      }
      System.out.println(baoStream.toString());
      
public class TcpServerDemo01 {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baoStream = null;

        try {
            // 1、创建服务器端口
            serverSocket = new ServerSocket(9999);
            while (true) {
                // 2、等待客户端连接
                socket = serverSocket.accept();
                // 3、读取客户端的消息
                is = socket.getInputStream();
                // 字节数组流
                baoStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while((len = is.read(buffer)) != -1) {
                    baoStream.write(buffer, 0, len);
                }
                System.out.println(baoStream.toString());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (baoStream != null) {
                try {
                    baoStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 客户端

    1. 创建服务器IP地址,端口号

      serverIP = InetAddress.getByName("127.0.0.1");
      int port = 9999;
      
    2. 创建socket连接

      Socket socket = new Socket(serverIP, port);
      
    3. 发送消息

      OutputStream os = socket.getOutputStream();
      os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
      
public class TcpClientDemo01 {
    public static void main(String[] args) {
        InetAddress serverIP =null;
        Socket socket = null;
        OutputStream os = null;

        try {
            // 1、创建服务器IP地址,端口号
            serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            // 2、创建一个socket连接
            socket = new Socket(serverIP, port);
            // 3、发送消息 IO流
            os = socket.getOutputStream();
            os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
image-20210220141127627

5.3 TCP发送文件

  • 客户端:
public class TcpClientDemo02 {
    public static void main(String[] args) throws IOException {
        // 1、创建Socket
        Socket socket = new Socket(InetAddress.getByName("localhost"), 9090);
        // 2、创建OutputStream
        OutputStream os = socket.getOutputStream();
        // 3、创建FileInputStream
        FileInputStream fis = new FileInputStream(new File("19伦.jpg"));
        // 4、写入文件
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fis.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }

        // 关闭输出,开始输入
        socket.shutdownOutput();

        // 确定服务器接受完毕
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer2 = new byte[1024];
        int len2 = 0;
        while((len = is.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        System.out.println(baos.toString());

        // 5、关闭资源
        fis.close();
        os.close();
        socket.close();
    }
}
  • 服务器端
public class TcpServerDemo02 {
    public static void main(String[] args) throws IOException {
        // 1、创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(9090);
        // 2、创建socket
        Socket socket = serverSocket.accept();
        // 3、创建getInputStream
        InputStream is = socket.getInputStream();
        // 4、创建FileOutputStream
        FileOutputStream fos = new FileOutputStream(new File("收到19伦.jpg"));
        // 5、解析数据
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }

        // 通知客户端接收完毕
        OutputStream os = socket.getOutputStream();
        os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));

        // 6、关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}
image-20210220155940879

5.4 TCP模板

// 客户端
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
OutputStream os = socket.getOutputStream();
os.write("自由啊 自由啊!".getBytes(StandardCharsets.UTF_8));
// 服务器端
ServerSocket serverSocket = new ServerSocket(9090);
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1) {
    baos.write(buffer, 0, len);
}
System.out.println(baos.toString());

发送文件见5.3节

5.5 Tomcat

服务器

  • 自定义 Server
  • Tomcat Server

客户端

  • 自定义 Client

  • 浏览器 Browser

Tomcat打开方式:

  1. 进入E:\EssentialSoftware\Apache-Tomcat-9.0.43\bin

  2. 打开startup.bat

  3. 浏览器打开http://localhost:8080/即可

5.6 UDP发送消息

客户端:

public class UdpClientDemo01 {
    public static void main(String[] args) throws IOException {
        // 1、数据报socket
        DatagramSocket socket = new DatagramSocket();
        // 2、新建packet(包)
        String msg = "你好啊????????????";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9000;
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.length(),
                                localhost, port);
        // 3、发送packet
        socket.send(packet);
        // 4、关闭socket
        socket.close();
    }
}

服务器端:

public class UdpServerDemo01 {
    public static void main(String[] args) throws IOException {
        // 1、数据报socket
        DatagramSocket socket = new DatagramSocket(9000);
        // 2、新建packet(用于接收数据)
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        // 3、阻塞接收packet
        socket.receive(packet);

        System.out.println(packet.getAddress());
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(), 0, packet.getLength()));

        // 4、关闭socket
        socket.close();
    }
}

5.7 UDP实现聊天

发送方:

public class UdpSender {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket();
        // 键盘输入
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String sendData = reader.readLine();
            byte[] sendDatas = sendData.getBytes();
            DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
                    new InetSocketAddress("localhost", 8888));

            socket.send(packet);

            if (sendDatas.equals("exit")) {
                break;
            }
        }
        socket.close();
    }
}

接收方:

public class UdpReceiver {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(8888);

        while (true) {
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

            socket.receive(packet);
            String receiveData = new String(packet.getData());
            System.out.println(receiveData);

            if (receiveData.equals("exit")) {
                break;
            }
        }
        socket.close();
    }
}
image-20210221172427675 image-20210221172457860

5.8 UDP多线程在线咨询

public class UdpTalkSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader reader = null;

    private int fromPort;
    private int toPort;
    private String toIP;

    public UdpTalkSend(int fromPort, int toPort, String toIP) {
        this.fromPort = fromPort;
        this.toPort = toPort;
        this.toIP = toIP;

        try {
            socket = new DatagramSocket(this.fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                String sendData = reader.readLine();
                byte[] sendDatas = sendData.getBytes();
                DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
                        new InetSocketAddress(this.toIP, this.toPort));

                socket.send(packet);
                if (sendData.equals("exit")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}
public class UdpTalkReceive implements Runnable{
    DatagramSocket socket = null;
    private String msgFrom;
    private int port;

    public UdpTalkReceive(String msgFrom, int port){
        this.msgFrom = msgFrom;
        this.port = port;
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                socket.receive(packet);

                String receiveData = new String(packet.getData());

                System.out.println(msgFrom + ":" + receiveData);
                if (receiveData.equals("exit")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

学生端:

public class UdpTalkStudent {
    public static void main(String[] args) {
        new Thread(new UdpTalkSend(7777, 9999, "localhost")).start();
        new Thread(new UdpTalkReceive("teacher", 8888)).start();
    }
}

老师端:

public class UdpTalkTeacher {
    public static void main(String[] args) {
        new Thread(new UdpTalkSend(5555, 8888, "localhost")).start();
        new Thread(new UdpTalkReceive("student", 9999)).start();
    }
}

5.9 UDP模板

// 发送方
DatagramSocket socket = new DatagramSocket();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
    String sendData = reader.readLine();
    byte[] sendDatas = sendData.getBytes();
    DatagramPacket packet = new DatagramPacket(sendDatas, 0, sendDatas.length,
                                               new InetSocketAddress("localhost", 8888));
    socket.send(packet);

    if (sendDatas.equals("exit")) {
        break;
    }
}
socket.close();
// 接收方
DatagramSocket socket = new DatagramSocket(8888);
while (true) {
    byte[] buffer = new byte[1024];
    DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
    
    socket.receive(packet);
    String receiveData = new String(packet.getData());
    System.out.println(receiveData);

    if (receiveData.equals("exit")) {
        break;
    }
}
socket.close();

6. URL

URL:Uniform Resource Locator (统一资源定位符),用于定位互联网上的某一个资源,每一个资源都有URL。

参考这篇文章

6.1 URL网址

http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument

protocol 😕/ hostname[:port] / path / [;parameters][?query]#fragment

mdn-url-protocol@x2_update

http 是协议。它表明了浏览器必须使用何种协议。它通常都是HTTP协议或是HTTP协议的安全版,即HTTPS。Web需要它们二者之一,但浏览器也知道如何处理其他协议,比如mailto:(打开邮件客户端)或者 ftp:(处理文件传输),所以当你看到这些协议时,不必惊讶。

mdn-url-domain@x2

www.example.com 是域名。 它表明正在请求哪个Web服务器。或者,可以直接使用IP address, 但是因为它不太方便,所以它不经常在网络上使用。.

mdn-url-port@x2

:80 是端口。 它表示用于访问Web服务器上的资源的技术“门”。如果Web服务器使用HTTP协议的标准端口(HTTP为80,HTTPS为443)来授予其资源的访问权限,则通常会被忽略。否则是强制性的。

mdn-url-path@x2

/path/to/myfile.html 是网络服务器上资源的路径。在Web的早期阶段,像这样的路径表示Web服务器上的物理文件位置。如今,它主要是由没有任何物理现实的Web服务器处理的抽象。

mdn-url-parameters@x2

?key1=value1&key2=value2 是提供给网络服务器的额外参数。 这些参数是用 &符号分隔的键/值对列表。在返回资源之前,Web服务器可以使用这些参数来执行额外的操作。每个Web服务器都有自己关于参数的规则,唯一可靠的方式来知道特定Web服务器是否处理参数是通过询问Web服务器所有者。

mdn-url-anchor@x2

#SomewhereInTheDocument 是资源本身的另一部分的锚点. 锚点表示资源中的一种“书签”,给浏览器显示位于该“加书签”位置的内容的方向。例如,在HTML文档上,浏览器将滚动到定义锚点的位置;在视频或音频文档上,浏览器将尝试转到锚代表的时间。值得注意的是,#后面的部分(也称为片段标识符(fragment))从来没有发送到请求的服务器。

6.2 URL下载网络文件

进入Tomcat下载地址

在/webapps/yifang下新建文件helloworld

打开Tomcat

public class URLDownloadFile {
    public static void main(String[] args) throws IOException {
        // 1、下载地址
        URL url = new URL("http://localhost:8080/yifang/helloworld");

        // 2、连接资源 Http
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream is = urlConnection.getInputStream();
        FileOutputStream fos = new FileOutputStream("helloworld.txt");

        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer, 0, len);
        }
		
        // 3、关闭资源
        fos.close();
        is.close();
        urlConnection.disconnect();
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值