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() + "下线");
        }
    }
}
相关推荐
代码中介商7 小时前
Linux TCP 网络编程完全指南:从三次握手到高并发服务器
服务器·网络·tcp/ip
咖喱o7 小时前
QinQ/VLAN Stacking
linux·运维·服务器·网络
sduwcgg8 小时前
IQ-Learn 在 RTX 3090 服务器上的环境配置与踩坑记录
运维·服务器
QFIUNE9 小时前
CD-HIT 详解:序列去冗余、安装使用与聚类结果解析
linux·服务器·机器学习·数据挖掘·conda·聚类
marsh02069 小时前
43 openclaw熔断与降级:保障系统在异常情况下的可用性
java·运维·网络·ai·编程·技术
摇滚侠9 小时前
Docker 如何查询挂载的目录
运维·docker·容器
勇闯逆流河10 小时前
【Linux】linux进程控制(进程池的详解与实现)
linux·运维·服务器
zhangfeng113311 小时前
部署到服务器上 宝塔系统 使用宝塔在线编辑器 FTP 批量上传 Git 部署 打包上传 codebudyy 编程程序开发
服务器·git·编辑器
WJ.Polar11 小时前
Scapy基本应用
linux·运维·网络·python
lljss202011 小时前
1. NameServer 域名服务器---NS
linux·服务器·前端