欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java网络编程入门(包含简单的实现聊天和网络爬虫)

程序员文章站 2022-06-05 19:57:12
...

1、网络编程概述

1.1 网络通信的两个要素

如何实现网络中的主机互相通信?

通信双方的地址 :

  • IP

  • 端口号

【比如说我们这里上课使用的就是局域网,你们连接到我的电脑,就能查看到我电脑的画面了】

一定的规则:(即,网络通信协议,有两套参考模型)

OSI 参考模型:模型过于理想化,未能在因特网上进行广泛推广!

TCP/IP 参考模型:TCP/IP协议,事实上的国际标准。

小总结:

  1. 网络编程中有两个主要的问题:

如何准确的定位网络上一台或多台主机;定位主机上的特定的应用;找到主机后如何可靠高效的进行数据传输

  1. 网络编程中的两个要素:
    • ip 和 端口号
  • 提供网络通信协议。 TCP/IP参考模型(应用层,传输层,网络层,物理+数据链路层)

1.2 Inet Address

ip地址:Inet Adderss

  • 唯一的标识 internet 上的计算机 ( 通信实体 )

  • 本地回环地址(hostAddress):127.0.0.1 主机名 ( hostName ):localhost

  • IP地址分类方式一 : IPV4 IPV6

    • IPV4:4个字节组成,4个0~255。大概42亿个, 30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
    • IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号 隔开,如2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b
  • IP地址分类方式2:公网地址(万维网使用) 和 私有地址(局域网使用)

    • 192.168.开头的就是私有地址,范围即为 192.168.0.0 ~ 192.168.255.255,专门为组织机构

      内部使用

  • 特点:不便于记忆,我们常使用域名来访问:www.baidu.com

    https://blog.kuangstudy.com/ => DNS 域名解析(150.109.117.44)=> 现在本机的hosts文件,

    判断是否有输入的域名地址,没有的话,再通过DNS服务器,找主机。

    hosts文件地址:c\windows\system32\drivers\etc\hosts


    InetAddressTest

try {
            //查询本机地址
            InetAddress inetAddress= InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress);

            InetAddress inetAddress1 =InetAddress.getByName("localhost");
            System.out.println(inetAddress1);
            InetAddress inetAddress2 = InetAddress.getLocalHost();
            System.out.println(inetAddress2);
            //查询网站ip地址
            InetAddress inetAddress3 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress3);
            //常用方法
            System.out.println(inetAddress3.getAddress());
            System.out.println(inetAddress3.getCanonicalHostName());//规范的名字
            System.out.println(inetAddress3.getHostAddress());//ip
            System.out.println(inetAddress3.getHostName());//域名或者自己电脑的名字
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

1.3 端口

端口表示计算机上的一个程序的进程:

  • 不同进程有不同的端口号!用来区分软件!
  • 被规定 0~65535
  • TCP,UDP : 655535*2 单个协议下,端口号不能冲突
  • 端口分类
    • 公有端口 0~1023
      • HTTP :80 HTTPS :443 FTP : 21 Telent :23
    • 程序注册端口: 1024~49151, 分配给用户和程序
      • Tomact :8080 MySQL :3306 Oracele :1521
    • 动态 , 私有:49152~65535
netstat  -ano #查看所有的端口
netstat -ano|findstr"5900"  #查看指定的端口
tasklist|findstr"8696"  #查看指定端口的进程

1.4 通信协议

协议: 约定,就好比我们现在说的是普通话

网络通信协议: 计算机网络中实现通信必须有一些约定,即通信协议,对速率,传输代码,代码结构,传输控制步骤,出错控制等制定标准。

通信协议分层的思想:在制定协议时,把复杂成份分解成一些简单的成份,再将他们复合起来。最常用的复合方式是层次方式,即同层间可以通信,上一层调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。

TCP/IP协议簇:

  • 传输层的两个重要协议:
    • 用户传输协议TCP(Transmission Control Protocol)
    • 用户数据报协议(User Datagram Protocol)
  • TCP/IP以其两个主要的协议:传输控制协议:TCP 和网络互连协议:IP ,是一组协议,包括多个具有不同功能的且互为关联的协议.
  • IP(Internet Protocol) 协议是网络层的主要协议,支持网间互联网的数据通信
  • TCP/IP协议模型从更实用的角度出发,形成了高效的四层体结构,即物理链路层,IP层,传输层和应用层

TCP和UDP对比:

  • TCP协议
    • 使用TCP协议前,必须建立TCP链接,形成传输数据通道;
    • 传输前,采用’三次握手’方式,点对点通信,是可靠的
    • TCP协议进行通信的两个应用进程:客户端,服务端
    • 在连接中可进行大数据量的传输
    • 传输完毕,需要释放已建立的连接,效率低
    • 类似于打电话
  • UDP协议
    • 将数据,源,目的封装成数据包,不需要建立连接
    • 每个数据包的大小限制在64k内
    • 发送方不管对方是否准备好,接收方收到也不确认,所以是不可靠的
    • 可以广播发送
    • 发送数据结束时,无需释放资源,开销小,速度快
    • 类似于发短信和导弹发射

2、TCP网络编程

2.1 案例一

客户端发送数据给服务端,服务端将数据展示在控制台上

//客户端
public class demo1 {
    public static void main(String[] args) {

        Socket socket = null;
        OutputStream os = null;
        try {
            //1.要知道服务器的地址和端口号
            InetAddress severIp = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2.创建一个socket连接
            socket = new Socket(severIp,port);
            //3.发送消息 IO流
            os = socket.getOutputStream();
            os.write("学习网络编程".getBytes());

        } catch (Exception 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();
                }
            }
        }
    }
}
//服务端
public class demo2 {

    public static void main(String[] args) {
        //1.我有一个地址
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            serverSocket = new ServerSocket(9999);
            socket = serverSocket.accept();
            is = socket.getInputStream();
            //管道流
            baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int len;
            while((len=is.read(bytes))!=-1){
                baos.write(bytes,0,len);
            }
            System.out.println(baos.toString());

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(baos!=null){
                try {
                  baos.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();
                }
            }
        }
    }
}

2.2 案例2

客户端发送文件给服务器,服务器保存在本地

public class test2 {
    public static void main(String[] args) throws Exception {
        //1.创建一个socket连接
        Socket socket = new Socket("127.0.0.1", 9091);
        //2.创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3.读取文件
        FileInputStream fil = new FileInputStream(new File("1.jpg"));
        //4.写出文件
        byte[] buffer = new byte[1024];
        int len;
        while((len=fil.read(buffer))!=-1){
            os.write(buffer,0,len);
        }

        //通知服务器我已经结束了
        socket.shutdownOutput();

        //确定服务器接收完毕,关闭连接
        InputStream inputStream = socket.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer2 = new byte[1024];
        int len2;
        while((len2=inputStream.read(buffer2))!=-1){
            baos.write(buffer2,0,len2);
        }
        baos.close();

        fil.close();
        socket.close();
    }
}
public class test1 {
    public static void main(String[] args) throws IOException {
        //1.创建服务
        ServerSocket serverSocket = new ServerSocket(9091);
        //2.监听客户端的连接
        Socket socket = serverSocket.accept();//阻塞时监听,会一直等待客户端连接
        //3.获取输入流
        InputStream is = socket.getInputStream();
        //4.文件输出
        FileOutputStream receive = new FileOutputStream(new File("receive"));
        byte[] buffer = new byte[1024];
        int len;
        while((len=is.read(buffer))!=-1){
            receive.write(buffer,0,len);
        }

        //通知客户端我接收完毕了
        OutputStream os = socket.getOutputStream();
        os.write("我接收完毕了".getBytes());

        receive.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

3、UDP网络编程

3.1 说明

  • DatagramSocket 和 DatagramPacket 两个类实现了基于UDP协议的网络程序。

  • UDP 数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安

  • 全送到目的地,也不确定什么时候可以抵达。

  • DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端

的IP地址和端口号。

  • UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接。如同发快

递包裹一样。

3.2 案例一

发送端

public static void main(String[] args) throws Exception {
        //1,建立DatagramSocket
        DatagramSocket socket = new DatagramSocket();
        //2. 封装数据包
        String msg = "send message";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9091;
        DatagramPacket packagt = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);

        //3.通过 Socket 发送 packet
        socket.send(packagt);
        //4. 关闭socket
        socket.close();
    }

接收端

public static void main(String[] args) throws IOException {
        //开放端口
        DatagramSocket socket = new DatagramSocket(9091);
        //接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
        socket.receive(packet);
        //byte[] data = packet.getData();
        String string = new String(packet.getData(),0,packet.getLength());
        System.out.println(string);
        socket.close();
    }

3.3 案例二:在线咨询

发送端

public static void main(String[] args) throws Exception {
        //1. 使用DatagramSocket 指定端口,创建发送端
        DatagramSocket socket = new DatagramSocket(8888);
        //2.准备数据,转成字节数据
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            String data = reader.readLine();
            byte[] datas = data.getBytes();
            //3. 封装成DatagramPacket包裹,需要指定目的地
            DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
            //4.发送包裹
            socket.send(packet);
            if(data.equals("bye")){
                break;
            }
        }
        socket.close();
    }

接收端

public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(6666);
        while (true) {
            //接受包裹
            byte[] contianer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(contianer, 0, contianer.length);
            socket.receive(packet);//阻塞式接受包裹

            byte[] datas = packet.getData();
            String data = new String(datas, 0, packet.getLength());
            System.out.println(data);
            if (data.equals("bye")) {
                break;
            }
        }
    socket.close();
   }

多线程进行接收和发送(实现自己和自己聊天)

//发送端
package com.kuang.lesson4;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
 * @date 2020/7/29 - 10:07
 */
public class TalkSend implements Runnable{
    DatagramSocket socket =null;
    BufferedReader reader =null;
    private int fromPort;
    private String toIp;
    private int toPort;

    public TalkSend(int fromPort, String toIp, int toPort) {
        this.fromPort = fromPort;
        this.toIp = toIp;
        this.toPort = toPort;
        try {
            socket = new DatagramSocket(fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {


        while (true) {
            String data = null;
            try {
                data = reader.readLine();
                byte[] datas = data.getBytes();

                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIp, this.toPort));

                socket.send(packet);
                if(data.equals("bye")){
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}
//接收端
package com.kuang.lesson4;

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

/**
 * @date 2020/7/29 - 10:08
 */
public class TalkReceive implements Runnable{
    DatagramSocket socket =null;
    private int Port;
    private String msg;

    public TalkReceive(int Port, String msg) {
        this.Port = Port;
        this.msg = msg;
        try {
            socket = new DatagramSocket(Port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        while (true) {
            try {
                byte[] contianer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(contianer, 0, contianer.length);
                socket.receive(packet);//阻塞式接受包裹
                byte[] datas = packet.getData();
                String data = new String(datas, 0, packet.getLength());
                System.out.println(msg+":"+data);
                if (data.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}
public class Talk2 {
    public static void main(String[] args) {
        new Thread(new TalkSend(5555,"localhost",2222)).start();
        new Thread(new TalkReceive(8888,"小虎")).start();
    }
}

public class Talk1 {
    public static void main(String[] args) {
        new Thread(new TalkSend(1111,"localhost",8888)).start();
        new Thread(new TalkReceive(2222,"小明")).start();
    }
}

**(通过小黑窗启动很帅,实现自己跟自己聊天(通过小黑窗启动记得加上包的路径))**

# 4、URL编程

## 4.1 url类

- URL (Uniform Resource Locator): 统一资源定位符,它表示 internet 上某一资源的地址

- 它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate:定位这个资源
- 通过URL 我们可以访问Internet上的各种网络资源,比如最常见的 www,ftp站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源
- URL 的 基本结构由 5部分组成:传输协议://主机名:端口号/文件名 #片段名?参数列表
  - 例如:http://localhost:8080/helloworld/index.txt#usernam=ahui&age=22
  - 片段名即锚链接,某些网站可以直接定位到某个章节位置
  - 参数列表格式: 参数名=参数值 & 参数名=参数值

```java
public class URLDemo01{
 	public static void main(String[] args) {
  		try{
            URL url = new URL("http://localhost:8080/helloworld/index.txt#usernam=ahui&age=22")
        }catch(MalformedURLException e){
            e.printStackTrace();
        }
    }
}

4.2 下载文件

从网络下载一首歌曲

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @date 2020/7/29 - 19:22
 */
public class urlPlay {
    public static void main(String[] args) throws Exception {
        //1.下载地址
        URL url = new URL("https://m801.music.126.net/20200729201137/7e808c84138cb5adac8622f4aa91a872/jdyyaac/5359/065a/5153/d379d139ee10b8a48b5cf9a973c983b0.m4a");
        //2.连接到资源 HTTP
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        InputStream is = connection.getInputStream();
        FileOutputStream fil = new FileOutputStream("a.mp4");

        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            fil.write(buffer,0,len);
        }
        fil.close();
        is.close();
        connection.disconnect();
    }
}

听了狂神的课算抄的吧,欢迎大家去b站给狂神三连

相关标签: java 网络