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 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> UDP和TCP编程 -> 正文阅读

[网络协议]UDP和TCP编程

UDP

特点:不建立连接;将数据源和目的封装成数据包中;

涉及类 DatagramSocket与DatagramPacket

public class DatagramSocket extends Object
描述:此类表示用来发送和接收数据报包的套接字。在 DatagramSocket 上总是启用 UDP 广播发送。

  • 构造方法
    • public DatagramSocket():构造数据报套接字并将其绑定到本地主机上任何可用的端口。
    • public DatagramSocket(SocketAddress bindaddr):创建数据报套接字,将其绑定到指定的本地套接字地址
    • public DatagramSocket(int port):创建数据报套接字并将其绑定到本地主机上的指定端口
    • public DatagramSocket(int port, InetAddress laddr):创建数据报套接字,将其绑定到指定的本地地址
  • 常用方法
    • public void send(DatagramPacket p):从此套接字发送数据报包。
    • public void receive(DatagramPacket p):从此套接字接收数据报包。

public final class DatagramPacket extends Object
描述:此类表示数据报包。数据报包用来实现无连接包投递服务。

  • 构造方法
    • public DatagramPacket(byte[] buf, int length):构造 DatagramPacket,用来接收长度为 length 的数据包。
    • public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
    • public DatagramPacket(byte[] buf, int offset, int length, SocketAddress address):构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
    • public DatagramPacket(byte[] buf, int length, InetAddress address, int port):构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
    • public DatagramPacket(byte[] buf, int length, SocketAddress address):构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
  • 常用方法
    • public InetAddress getAddress():获取数据报将要发往该机器或者是从该机器接收的 InetAddress 地址(通常为 IP 地址)。
    • public SocketAddress getSocketAddress():获取要将此包发送到的或发出此数据报的远程主机的 SocketAddress(通常为 IP 地址 + 端口号)。
    • public byte[] getData():返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量 offset 处开始,持续 length 长度。

client发送端思路

  1. 建立udp的socket服务。
  2. 将要发送的数据封装成数据包。
  3. 通过udp的socket服务,将数据包发送出。
  4. 关闭资源。

client发送端代码

public class UdpClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建发送端DatagramSocket对象
        DatagramSocket ds = new DatagramSocket();

        // 创建数据
        byte[] bys = "hello,udp,我来了".getBytes();
        // 长度
        int length = bys.length;
        // IP地址对象
        InetAddress address = InetAddress.getByName("192.168.0.106");
        // 端口
        int port = 10086;

        // 创建数据,并把数据打包
        // DatagramPacket(byte[] buf, int length, InetAddress address, int port)
        DatagramPacket dp = new DatagramPacket(bys, length, address, port);

        // 调用Socket对象的发送方法发送数据包
        // public void send(DatagramPacket p)
        ds.send(dp);

        // 释放资源
        ds.close();
    }
}

server接收端思路

  1. 建立udp的socket服务。
  2. 通过receive方法接收数据。
  3. 将收到的数据存储到数据包对象中。
  4. 通过数据包对象的功能来完成对接收到数据进行解析。
  5. 可以对资源进行关闭。

server接收端代码

public class UdpServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建接收端DatagramSocket对象
        DatagramSocket ds = new DatagramSocket(10086);

        // 创建一个数据包(接收容器)
        // DatagramPacket(byte[] buf, int length)
        byte[] bys = new byte[1024];
        int length = bys.length;
        DatagramPacket dp = new DatagramPacket(bys, length);

        // 调用Socket对象的接收方法接收数据
        // public void receive(DatagramPacket p)
        ds.receive(dp); // 阻塞式

        // 解析数据包,并显示在控制台
        // 获取对方的ip
        // public InetAddress getAddress()
        String ip = dp.getAddress().getHostAddress();

        // public byte[] getData():获取数据缓冲区
        // public int getLength():获取数据的实际长度
        byte[] bys2 = dp.getData();
        int len = dp.getLength();
        String s = new String(bys2, 0, len);
        System.out.println(ip + "传递的数据是:" + s);

        // 释放资源
        ds.close();
    }
}

运行服务端后,ds.receive(dp);该方法会一直阻塞等待数据。当客户端运行后,服务端打印“192.168.0.106传递的数据是:hello,udp,我来了”结束。

UDP案例

案例一

客户端:从键盘录入数据进行发送,如果输入的是886那么客户端就结束输入数据。
服务端:一直输出客户端发来的数据。

客户端-UdpClientDemo:
public class UdpClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建发送端的Socket对象
        DatagramSocket ds = new DatagramSocket();

        // 封装键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while ((line = br.readLine()) != null) {
            if ("886".equals(line)) {
                break;
            }

            // 创建数据并打包
            byte[] bys = line.getBytes();
            // DatagramPacket dp = new DatagramPacket(bys, bys.length,
            // InetAddress.getByName("192.168.0.106"), 12345);
            DatagramPacket dp = new DatagramPacket(bys, bys.length,
                    InetAddress.getByName("192.168.0.255"), 12345);

            // 发送数据
            ds.send(dp);
        }

        // 释放资源
        ds.close();
    }
}

服务端-UdpServerDemo:
public class UdpServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建接收端的Socket对象
        DatagramSocket ds = new DatagramSocket(12345);

        while (true) {
            // 创建一个包裹
            byte[] bys = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bys, bys.length);

            // 接收数据
            ds.receive(dp);

            // 解析数据
            String ip = dp.getAddress().getHostAddress();
            String s = new String(dp.getData(), 0, dp.getLength());
            System.out.println("from " + ip + " data is : " + s);
        }

        // 释放资源
        // 接收端应该一直开着等待接收数据,是不需要关闭
        // ds.close();
    }
}

上述 DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName(“192.168.0.255”), 12345);中,192.168.0.255为广播地址,该网段所有主机均可接收。

案例二

发送和接收程序分别用线程进行封装,完成一个UDP的聊天程序。

客户端-UdpClientDemo 
public class UdpClientDemo implements Runnable{
    public DatagramSocket ds;

    public UdpClientDemo(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            // 封装键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = br.readLine()) != null) {
                if ("886".equals(line)) {
                    break;
                }

                // 创建数据并打包
                byte[] bys = line.getBytes();
                DatagramPacket dp = new DatagramPacket(bys, bys.length,
                        InetAddress.getByName("192.168.0.255"), 12306);

                // 发送数据
                ds.send(dp);
            }

            // 释放资源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端-UdpServerDemo 
public class UdpServerDemo implements Runnable {
    public DatagramSocket ds;

    public UdpServerDemo(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            while (true) {
                // 创建一个包裹
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys, bys.length);

                // 接收数据
                ds.receive(dp);

                // 解析数据
                String ip = dp.getAddress().getHostAddress();
                String s = new String(dp.getData(), 0, dp.getLength());
                System.out.println("from " + ip + " data is : " + s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

聊天室:
public class ChatRoom {
    public static void main(String[] args) throws IOException {
        DatagramSocket dsSend = new DatagramSocket();
        DatagramSocket dsReceive = new DatagramSocket(12306);

        UdpClientDemo client = new UdpClientDemo(dsSend);
        UdpServerDemo server = new UdpServerDemo(dsReceive);

        Thread t1 = new Thread(client);
        Thread t2 = new Thread(server);

        t1.start();
        t2.start();
    }
}

TCP

特点:建立连接;形成传输数据的通道,在连接中进行大数据量传输;

涉及类Socket和ServerSocket

public class Socket extends Object
描述:此类实现客户端套接字

  • 构造函数
    • public Socket(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。
      • host - 主机名,或者为 null,表示回送地址。
      • port - 端口号。
    • public Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号
      • address - IP 地址。
      • port - 端口号。
    • public Socket(String host, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程主机上的指定远程端口。
      • host - 远程主机名,或者为 null,表示回送地址。
      • port - 远程端口
      • localAddr - 要将套接字绑定到的本地地址
      • localPort - 要将套接字绑定到的本地端口
    • public Socket(InetAddress address, int port, InetAddress localAddr, int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。
      • address - 远程地址
      • port - 远程端口
      • localAddr - 要将套接字绑定到的本地地址
      • localPort - 要将套接字绑定到的本地端口
  • 常用方法
    • public void connect(SocketAddress endpoint):将此套接字连接到服务器。
    • public SocketChannel getChannel():返回与此数据报套接字关联的唯一 SocketChannel 对象(如果有)。
    • public InputStream getInputStream():返回此套接字的输入流。
    • public OutputStream getOutputStream():返回此套接字的输出流。
    • public void close():关闭此套接字。

public class ServerSocket extends Object
描述:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

  • 构造函数
    • public ServerSocket(int port):创建绑定到特定端口的服务器套接字。
    • public ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
  • 常用方法
    • public Socket accept():侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞
    • public void close():关闭此套接字。
    • public ServerSocketChannel getChannel():返回与此套接字关联的唯一 ServerSocketChannel 对象(如果有)。

client发送端思路

  1. 建立客户端的socket服务,并明确要连接的服务器。
  2. 如果连接建立成功,就表明已经建立了数据传输的通道。就可以在该通道通过IO进行数据的读取和写入。该通道称为Socket流,Socket流中既有读取流,也有写入流。
  3. 通过Socket对象的方法,获取读取流、写入流。
  4. 通过流对象可以对数据进行传输。
  5. 如果传输数据完毕,关闭资源。

client发送端代码

public class TcpClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket s = new Socket("192.168.0.106", 22222);

        // 键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 包装通道内的输出流
        PrintWriter printWriter = new PrintWriter(s.getOutputStream(), true);

        String line = null;
        while ((line = br.readLine()) != null) {
            // 键盘录入数据要自定义结束标记
            if ("886".equals(line)) {
                break;
            }

            // 往通道内写入数据
            printWriter.println(line);

            // 包装通道内的输入流
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(s.getInputStream()));

            // 读取通道内数据
            String readLine = bufferedReader.readLine();
            System.out.println("接收数据:" + readLine);
        }

        // 释放资源
        // bw.close();
        // br.close();
        s.close();
    }
}

server接收端思路

  1. 建立服务器端的socket服务,绑定一个端口。
  2. 通过accept方法获取客户端对象,再通过获取到的客户端对象的流和客户端进行通信。
  3. 通过客户端的获取流对象的方法,读取数据或者写入数据。
  4. 如果服务完成,需要关闭客户端,然后关闭服务器。但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的。

server接收端代码

public class TcpServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务器Socket对象
        ServerSocket ss = new ServerSocket(22222);

        // 监听客户端连接
        Socket s = ss.accept();

        // 包装通道内容的输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(
                s.getInputStream()));
        String line = null;

        while ((line = br.readLine()) != null) {
            System.out.println(s.getInetAddress().getHostAddress() + "---" + line);

            // 包装通道内的输出流
            PrintWriter printWriter = new PrintWriter(s.getOutputStream(), true);
            // 往通道内写入数据
            printWriter.println("服务器响应数据" + line);
        }

        // br.close();
        s.close();
        // ss.close();
    }
}

先启动服务端,再启动客户端。
111
接收数据:服务器响应数据111
22
接收数据:服务器响应数据22
886

TCP案例

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:33:55  更:2021-08-09 10:35:28 
 
开发: 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年12日历 -2024/12/28 6:15:45-

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