IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> JAVA 笔记 12 网络 -> 正文阅读

[网络协议]JAVA 笔记 12 网络

网络编程

基本概念

????计算机网络是通过传输介质、通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来的,实现资源共享和数据传输的系统。网络编程就是编写程序使互联网的两个(或多个)设备(如计算机)之间进行数据传输。

百度百科:分类 | 分层 | IP | 端口 | 套接字 | TCP | UDP | URL | URI

InetAddress 类

InetAddress 类,表示IP地址。

常用方法

  • byte[] getAddress() :返回原始 IP 地址;
  • static InetAddress getByName(String host) :在给定主机名的情况下确定主机的 IP 地址;
  • String getHostAddress() :返回 IP 地址字符串;
  • String getHostName() :获取此 IP 地址的主机名;
  • static InetAddress getLocalHost() :返回本地主机。

InetSocketAddress 类

InetSocketAddress类,实现 IP套接字地址(IP 地址 + 端口号)。

构造方法

  • InetSocketAddress(InetAddress addr, int port) :根据 IP 地址和端口号创建套接字地址;
  • InetSocketAddress(int port) :创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值;
  • InetSocketAddress(String hostname, int port) :根据主机名和端口号创建套接字地址。

常用方法

  • InetAddress getAddress() :获取 InetAddress;
  • String getHostName() :获取 hostname;
  • int getPort() :获取端口号。

TCP网络编程

Socket 类

Socket 类,实现客户端套接字,套接字指的是两台设备之间通讯的端点。

构造方法

public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。

常用方法

  • public InputStream getInputStream() : 返回此套接字的输入流;
  • public OutputStream getOutputStream() : 返回此套接字的输出流;
  • public void close() :关闭此套接字;
  • public void shutdownOutput() : 禁用此套接字的输出流。

ServerSocket 类

ServerSocket类,实现了服务器套接字,该对象等待通过网络的请求。

构造方法

public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。

常用方法

  • public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。

代码实现

示例1

  • 客户端向服务端发送消息;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

@Slf4j
public class TCPDomo {

    private static final String HOST = "127.0.0.1";

    private static final Integer PORT = 8080;

    /**
     * 服务端
     */
    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;
        try {
            // 创建服务端的ServerSocket,指明自己的端口号
            serverSocket = new ServerSocket(PORT);

            // 调用accept接收到来自于客户端的socket
            // 阻塞式监听,会一直等待客户端的接入
            socket = serverSocket.accept();

            // 获取socket的输入流
            inputStream = socket.getInputStream();

            // 读取输入流中的数据
            outputStream = new ByteArrayOutputStream();
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            log.info("收到了来自于客户端 [{}] 的消息:{}", socket.getInetAddress().getHostName(), outputStream.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 客户端
     */
    @Test
    public void client() {
        Socket socket = null;
        OutputStream os = null;
        try {
            // 创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
            InetAddress inet = InetAddress.getByName(HOST);
            socket = new Socket(inet, PORT);
            // 获取一个输出流,用于写出要发送的数据
            os = socket.getOutputStream();
            // 写出数据
            os.write("你好,我是客户端!".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

示例2

  • 客户端向服务端发送消息;
  • 服务端发向客户端回复消息;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

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

@Slf4j
public class TCPDomo {

    private static final String HOST = "127.0.0.1";

    private static final Integer PORT = 8080;

    /**
     * 服务端
     */
    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        OutputStream outputStream = null;
        try {
            // 创建服务端的ServerSocket,指明自己的端口号
            serverSocket = new ServerSocket(PORT);
            // 调用accept接收到来自于客户端的socket
            // 阻塞式监听,会一直等待客户端接入
            socket = serverSocket.accept();
            // 获取socket的输入流
            inputStream = socket.getInputStream();

            // 读取输入流中的数据
            byteArrayOutputStream = new ByteArrayOutputStream();
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, len);
            }
            log.info("收到了来自于客户端 [{}] 的消息:{}", socket.getInetAddress().getHostName(), byteArrayOutputStream.toString());
            // ===========================回复==========================================
            // 获取一个输出流,写出回复给客户端
            outputStream = socket.getOutputStream();
            // 写出数据
            outputStream.write("你好,我是服务端".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 客户端
     */
    @Test
    public void client() {
        Socket socket = null;
        OutputStream outputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        InputStream inputStream = null;
        try {
            // 创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
            InetAddress inet = InetAddress.getByName(HOST);
            socket = new Socket(inet, PORT);
            // 获取一个输出流,用于写出要发送的数据
            outputStream = socket.getOutputStream();
            // 写出数据
            outputStream.write("你好,我是客户端!".getBytes());
            // ==========================解析回复==================================
            // 首先必须通知服务器,我已经输出完毕了,不然服务端不知道什么时候输出完毕
            // 服务端的while循环会一直执行,会阻塞
            socket.shutdownOutput();
            // 获取输入流,用于读取服务端回复的数据
            inputStream = socket.getInputStream();
            byteArrayOutputStream = new ByteArrayOutputStream();
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, len);
            }
            log.info("收到了来自服务端的消息:{}", byteArrayOutputStream.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}  

示例3

  • 上传文件:客户端发送文件给服务端,服务端将文件保存在本地
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

@Slf4j
public class TCPDomo {

    private static final String HOST = "127.0.0.1";

    private static final Integer PORT = 8080;

    /**
     * 服务端
     */
    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        try {
            // 创建服务端的ServerSocket,指明自己的端口号
            serverSocket = new ServerSocket(PORT);
            // 调用accept接收到来自于客户端的socket
            //阻塞式监听,会一直等待客户端的接入
            socket = serverSocket.accept();
            // 创建一个文件输出流,用于将读取到的客户端上传的文件输出
            fileOutputStream = new FileOutputStream("image.jpg");
            // 获取socket的输入流
            inputStream = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            // 写出文件
            while ((len = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 客户端
     */
    @Test
    public void client() {
        Socket socket = null;
        FileInputStream fileInputStream = null;
        OutputStream outputStream = null;
        try {
            // 创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
            InetAddress inet = InetAddress.getByName(HOST);
            socket = new Socket(inet, PORT);
            // 创建一个文件输入流,读取要上传的文件
            fileInputStream = new FileInputStream("D:/image.jpg");
            // 获取一个输出流,用于写出要发送的数据
            outputStream = socket.getOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            // 写出数据
            while ((len = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

UDP网络编程

对于UDP来说,严格意义上,并没有所谓的Server和Client。

java.net包给我们提供了两个类DatagramSocket(用于发送和接收数据报的套接字)和DatagramPacket(数据报的数据包。 )

DatagramSocket

构造方法

protected DatagramSocket()构造数据报套接字并将其绑定到本地主机上的任何可用端口;
protected DatagramSocket(int port)构造数据报套接字并将其绑定到本地主机上的指定端口;
protected DatagramSocket(int port, InetAddress laddr)创建一个数据报套接字,绑定到指定的本地地址。

DatagramPacket

构造方法

DatagramPacket(byte[] buf, int offset, int length)构造一个 DatagramPacket用于接收指定长度的数据报包到缓冲区中;
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)构造用于发送指定长度的数据报包到指定主机的指定端口号上。

常用方法

byte[] getData() :返回数据报包中的数据;
InetAddress getAddress():返回该数据报发送或接收数据报的计算机的IP地址;
int getLength():返回要发送的数据的长度或接收到的数据的长度。

代码实现

示例1

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

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

@Slf4j
public class UDPDemo {

    private static final String HOST = "127.0.0.1";

    private static final Integer PORT = 8080;

    /**
     * 接收方
     */
    @Test
    public void receive() throws IOException {
        // 创建一个socket,开放端口
        DatagramSocket socket = new DatagramSocket(PORT);
        byte[] buffer = new byte[1024];
        // 创建一个包接收数据
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        // 接收数据
        socket.receive(packet);//阻塞式接收
        // 将数据包转换为字符串输出
        String msg = new String(packet.getData(), 0, packet.getLength());
        log.info("接收到消息:[{}]", msg);
        // 释放资源
        socket.close();
    }

    /**
     * 发送方
     */
    @Test
    public void send() throws IOException {
        // 创建一个socket
        DatagramSocket socket = new DatagramSocket();
        InetAddress inet = InetAddress.getByName(HOST);
        String msg = "你好,很高兴认识你!";
        byte[] buffer = msg.getBytes();
        // 创建一个包(要发送给谁)
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, PORT);
        // 发送包
        socket.send(packet);
        // 释放资源
        socket.close();
    }
    
}

示例2

完成在线咨询功能,学生和老师在线一对一交流(多线程)。

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

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

@Slf4j
public class UDPDemo {

    private static final String HOST = "127.0.0.1";

    private static final Integer PORT_1 = 8080;

    private static final Integer PORT_2 = 9090;

    /**
     * 发送方
     */
    class Sender implements Runnable {

        // 创建一个socket
        DatagramSocket socket = null;

        // 创建一个流 用于录入键盘的数据
        BufferedReader bufferedReader = null;

        // 发送数据目的地的IP
        private String toIP;

        // 发送数据目的地的端口
        private int toPort;

        public Sender(String toIP, int toPort) {
            this.toIP = toIP;
            this.toPort = toPort;
            try {
                // 创建一个socket
                socket = new DatagramSocket();
            } catch (SocketException e) {
                e.printStackTrace();
            }
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));//从键盘录入数据到流中
        }

        @Override
        public void run() {
            // 循环发送数据
            while (true) {
                try {
                    //从流中读取数据
                    String msg = bufferedReader.readLine();
                    byte[] buffer = msg.getBytes();
                    InetAddress inet = InetAddress.getByName(toIP);
                    DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, toPort);
                    socket.send(packet);
                    // 如果发送了拜拜,则退出发送
                    if (msg.equals("拜拜")) {
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //释放资源
            if (socket != null) {
                socket.close();
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 接收方
     */
    class Receiver implements Runnable {
        // 创建一个socket
        DatagramSocket socket = null;

        // 接收方自己所在的端口
        private int fromPort;

        // 数据发送者的姓名
        private String msgFrom;

        public Receiver(int fromPort, String msgFrom) {
            this.fromPort = fromPort;
            this.msgFrom = msgFrom;
            try {
                socket = new DatagramSocket(fromPort);//创建一个socket
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            // 循环接收
            while (true) {
                try {
                    byte[] buffer = new byte[1024 * 8];
                    DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                    socket.receive(packet);
                    String msg = new String(packet.getData(), 0, packet.getLength());
                    log.info("{}:{}", msgFrom, msg);
                    if (msg.equals("拜拜")) {//如果接收到的数据为拜拜,则退出接收
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 释放资源
            socket.close();
        }
    }

    /**
     * 老师线程
     */
    @Test
    public void receive() {
        new Thread(new Sender(HOST, PORT_1)).start();
        new Thread(new Receiver(PORT_2, "学生")).start();
    }

    /**
     * 学生线程
     */
    @Test
    public void send() {
        new Thread(new Sender(HOST, PORT_2)).start();
        new Thread(new Receiver(PORT_1, "老师")).start();
    }

}

URL 类

构造方法

  • URL(String spec):根据 String 表示形式创建 URL 对象;
  • URL(String protocol, String host, int port, String file):根据指定协议名、主机名、端口号和文件名创建 URL 对象;
  • URL(String protocol, String host, String file):根据指定的协议名、主机名和文件名创建 URL。

常用方法

  • String getProtocol():获取此 URL的协议名称;
  • String getHost():获取此 URL 的主机名;
  • int getPort():获取此 URL 的端口号;
  • String getPath():获取此 URL 的文件路径;
  • String getFile():获取此 URL 的文件名;
  • String getQuery():获取此 URL的查询部分;
  • URLConnection openConnection():返回一个URLConnection实例,表示与URL引用的远程对象的URL 。
    • URLConnection类中有一个方法:InputStream getInputStream():返回从此打开的连接读取的输入流。

示例

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

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

@Slf4j
public class URLDemo {

    @Test
    public void visit() throws MalformedURLException {
        URL url = new URL("https://www.baidu.com/");
        log.info("获取协议名: {}", url.getProtocol());
        log.info("获取主机名: {}", url.getHost());
        log.info("获取端口号: {}", url.getPort());
        log.info("获取文件路径: {}", url.getPath());
        log.info("获取文件名: {}", url.getFile());
        log.info("获取查询名: {}", url.getQuery());
    }

    @Test
    public void download() throws IOException {
        // 下载地址
        URL url = new URL("https://i0.hdslb.com/bfs/activity-plat/static/20190409/7d3fbe1b994526c1fae2b51bb7f2b633/S114GfcFE.png");
        // 连接到这个资源 HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        InputStream is = urlConnection.getInputStream();
        FileOutputStream fos = new FileOutputStream("bilibili.png");
        byte[] buffer = new byte[1024];
        int len=0;
        while ((len=is.read(buffer))!=-1){
            fos.write(buffer, 0, len);
        }
        // 释放资源
        urlConnection.disconnect();
        is.close();
        fos.close();
    }

}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-22 20:59:39  更:2022-02-22 21:01:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:27:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码