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() + "下线");
        }
    }
}
相关推荐
Ztiddler5 小时前
【Linux Shell命令-不定期更新】
linux·运维·服务器·ssh
小小不董5 小时前
Oracle OCP认证考试考点详解082系列16
linux·运维·服务器·数据库·oracle·dba
IPdodo全球网络5 小时前
如何利用静态住宅IP优化Facebook商城的网络稳定性与运营效率
运维·服务器
a1denzzz5 小时前
Linux系统的网络设置
linux·服务器·网络
运维&陈同学6 小时前
【模块一】kubernetes容器编排进阶实战之k8s基础概念
运维·docker·云原生·容器·kubernetes·云计算
m0_519523106 小时前
Linux——简单认识vim、gcc以及make/Makefile
linux·运维·vim
mit6.8246 小时前
[Docker#4] 镜像仓库 | 部分常用命令
linux·运维·docker·容器·架构
zyp2468107 小时前
Linux之DNS服务器
linux·运维·服务器
wdxylb7 小时前
将C++搭建的简单HTTP服务器升级为 HTTPS 服务器
运维·服务器·https
Denzel张7 小时前
ubuntu_dpkg_dep_list
linux·运维·ubuntu