Java(十)(网络编程,UDP,TCP)

目录

网络编程

两种软件架构

网络通信的三要素

IP

IPv4的地址分类

特殊IP

端口号

协议

用UDP协议发送数据

用UDP接收数据

TCP接收和发送数据

TCP通信--支持与多个客户端同时通信


网络编程

可以让设备中的程序与网络上其他设备的程序进行数据交互(实现网络通信)

两种软件架构

CS:在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序

BS:只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器

网络通信的三要素

IP

设备在网络中的地址,是唯一的标识

有IPv4和IPv6

最多有2^32次方的ip,目前用完了

IPv4中不够用,就有了IPv6

为了解决ipv4不够用而出现的,最多有2^128次方的ip

IPv4的地址分类

公网地址(万维网使用)和私有地址(局域网使用)

192.168.开头的就是私有地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用,以此节约IP

特殊IP

127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也成为本机IP,永远只会寻找当前所在的本机

常用的CMD命令

ipconfig:查看本机IP地址

ping:检查网络是否连通

复制代码
public class ip {
    public static void main(String[] args) throws UnknownHostException {
        // 1.获取InetAddress的对象
        // IP的对象  一台电脑对象
        InetAddress address = InetAddress.getByName("192.168.135.1");
        System.out.println(address);
        String name = address.getHostName();
        System.out.println(name);
        String ip = address.getHostAddress();
        System.out.println(ip);
    }
}

端口号

应用程序在设备中唯一的标识

端口号: 由两个字节表示的整数,取值范围:0-665535,其中0-1023之间的端口用于一些知名的网络服务或应用,我们自己使用1024以上的端口就可以了

协议

数据在网路中传输的规则

UDP协议: 用户数据报协议

UDP是面向无连接通信协议

速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据

TCP协议:传输控制协议

TCP协议是面向连接的通信协议

速度慢,没有大小限制,数据安全

下面是用UDP来发收数据

用UDP协议发送数据
复制代码
public class ip {
    public static void main(String[] args) throws IOException {
        // 发送数据
        // 1.创建DatagramSocket对象
        // 细节:
        //绑定端口,以后我们就是通过这个端口往外发送
        //有参:指定端口号进行绑定
        DatagramSocket ds = new DatagramSocket();

        // 打包数据
        String str = "hello world";
        byte[] bytes = str.getBytes(); // 将str转换成字节数组来用来打包数据
        InetAddress address = InetAddress.getByName("127.0.0.1");  // 表示那台ip电脑来接受
        int port=10086; //被发数据电脑接收的端口
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);

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

        // 4.释放资源
        ds.close();
    }
}
用UDP接收数据
复制代码
public class receive {
    public static void main(String[] args) throws IOException {
        // 接收数据

        // 1.创建DatagramSocket对象//我们可以做一个比喻: 这就是一个快递公司
        // 细节:
        // 接收和传输不一样:接收一定要绑定接口
        // 而且绑定的端口,一定要跟发送的端口保持一致
        DatagramSocket ds = new DatagramSocket(10086);

        // 2. 接收数据包
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
        ds.receive(dp);

        // 3.解析数据包
        byte[] data = dp.getData();
        int len = dp.getLength();
        InetAddress address = dp.getAddress();
        int port = dp.getPort();

        System.out.println("接收到数据" + new String(data,len));
        System.out.println("该数据是从"+address+"接口是"+port);

        // .释放资源
        ds.close();
    }
}
TCP接收和发送数据

通信双方事先会采用"三次握手"方式建立可靠连接,实现端到端的通信;底层能保证数据成功传到服务端

一发一收

创建客户端

复制代码
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Tcp {
    public static void main(String[] args) throws IOException {
        // 1.创建Socket对象,并同时请求与服务器程序的连接
        Socket socket = new Socket("127.0.0.1",8888);

        // 2.从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        // 3.把低级的字节输出流包装成数据流
        DataOutputStream dos = new DataOutputStream(os);

        //4.开始写数据出去了
        dos.writeUTF("在一起,好吗?");
        dos.close();

        socket.close();

    }
}

创建服务器

复制代码
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Res {
    public static void main(String[] args) throws IOException {
        System.out.println("------服务端启动成功------");
        // 1.创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);
        // 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept();
        
        // 3. 从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        //4.把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        //5.使用数据输入流读取客户端发送的消息
        String rs = dis.readUTF();
        System.out.println(rs);

        // 其实我们也可以获取客户端的IP地址
        System.out.println(socket.getRemoteSocketAddress());

        dis.close();
        socket.close();
    }
}

多发多收

发送数据

复制代码
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Tcp {
    public static void main(String[] args) throws IOException {
        // 1.创建Socket对象,并同时请求与服务器程序的连接
        Socket socket = new Socket("127.0.0.1",8888);

        // 2.从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();


        // 3.把低级的字节输出流包装成数据流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);


        while (true) {
            System.out.println("请说: ");
            String msg = sc.nextLine();
            // 一旦用户输入exit,就退出客户端程序
            if("exit".equals(msg)){
                System.out.println("欢迎你下次光临!退出成功");
                dos.close();
                socket.close();
                break;
            }
            //4.开始写数据出去了
            dos.writeUTF(msg);
            dos.flush();
        }
    }
}

接收数据

复制代码
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Res {
    public static void main(String[] args) throws IOException {
        System.out.println("------服务端启动成功------");
        // 1.创建ServerSocket的对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8888);
        // 2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept();
        
        // 3. 从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream();

        //4.把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        while (true) {
            try {
                //5.使用数据输入流读取客户端发送的消息
                String rs = dis.readUTF();
                System.out.println(rs);
            } catch (IOException e) {
                System.out.println(socket.getRemoteSocketAddress()+"离线了");
                socket.close();
                dis.close();
                break;
            }
        }


    }
}
TCP通信--支持与多个客户端同时通信

我们应该整一个多线程的写法,每个客户端写成一个线程

创建客户端

复制代码
public class tcp {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999);
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        // 1. 多发多收
        Scanner sc = new Scanner(System.in);

        while (true) {
            String msg = sc.nextLine();
            if("886".equals(msg)){
                System.out.println("下线");
                break;
            }
            dos.writeUTF(msg);
        }
    }
}

创建服务端

复制代码
public class res {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket =new ServerSocket(9999);
        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("有人上线了"+socket.getRemoteSocketAddress());
            new SeverSocketThread(socket).start();
        }
    }
}

我们看看线程的写法

复制代码
package TCP_test;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SeverSocketThread extends Thread{
    private Socket socket;

    public SeverSocketThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run()
    {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true) {
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                } catch (Exception e) {
                    System.out.println("有人下线了"+socket.getRemoteSocketAddress());
                    dis.close();
                    is.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            System.out.println(socket.getRemoteSocketAddress() + "下线");
        }
    }
}
相关推荐
七夜zippoe12 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥12 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
Fcy64813 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满14 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠14 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
主机哥哥14 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Harvey90314 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技15 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀15 小时前
Linux环境变量
linux·运维·服务器
zzzsde16 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器