Java基础(二十四)——网络编程、InetAddress类、基于 TCP 协议的通信以及相关案例(传输文本、对象、多客户端链接服务端、上传图片)、基于UDP协议的传输

本文深入讲解了Java中的网络编程基础,包括IP地址、端口号和协议的概念。详细阐述了InetAddress类的用途,并通过实例展示了基于TCP协议的文本、对象传输以及多客户端连接服务端的实现。此外,还探讨了基于UDP协议的简单文本传输。文章最后介绍了如何使用Java进行图片上传操作,以及如何通过UDP进行数据报包的发送与接收。
摘要由CSDN通过智能技术生成

Java基础(二十四)——网络编程、InetAddress类、基于 TCP 协议的通信以及相关案例(传输文本、对象、多客户端链接服务端、上传图片)、基于UDP协议的传输

一、网络编程

1、相关概念

1.计算机网络:将不同地区的电脑 使用网络进行连接 从而实现数据的交互与共享

2.网络编程三要素:IP地址 端口号 协议

3.IP地址:IP地址是计算机在网络中的唯一的标识

4.IP分类:IP4与IP6
	IP4:192.168.1.130 10.3.138.115 子网
	IP4是有4个字节的二进制组成 记忆比较麻烦 目前都是十进制表示形式
	IP6是由十六进制组成的
	
5.查看IP
	第一步 windons+r
	第二步 输入cmd
	第三步输入 ipconfig
6.检查服务器是否连接成功 ping +IP地址

7.端口号:端口是进程在计算机中唯一的标识 端口号范围 0-65535 1-1024(一般是系统的端口号 不建议使用)

8.常用的端口号:
	mysql:3306
	qq:4000
	oralce:1521
	tomcat:8080

2、协议

1.协议:网络传输数据的规则 必须遵循这个规则才能进行数据的交互。

2.常见的协议:
	TCP:面向连接的协议,三次握手,传输效率低,不会出现丢失数据 丢包。
	UDP:面向无连接的协议,传输的效率高,会丢失数据(短信群发)。
	HTTP:一次性连接协议,客户端与服务器交互成功就断开,大部分的web项目的都是使用HTTP协议,效率快,
		  安全性高,HTTP传输的数据的时候没有对数据进行加密。
	HTTPS = HTTP+SSL。SL证书传输数据的时候会对数据进行加密传输 保证数据的安全性。

二、InetAddress 类

此类表示互联网协议 (IP) 地址 UDP 和 TCP 协议都是在它的基础上构建的。
在这里插入图片描述

下面是方法的使用:
在这里插入图片描述

三、基于 TCP 协议的通信

.此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。

1、常用方法

构造方法:
在这里插入图片描述
在这里插入图片描述

2、案例(一)——传输简单的文本

既然是通信,就需要两个端来互相说话,一般分为服务端跟客户端。

客户端代码:

public class Demo1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost",8899);    //  实例化 Socket 。localhost:表示本机IP地址。也可以手动填数字。

        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();     //  获得输入流和输出流

        String str = "屌你老母";        //  要传输的文本

        os.write(str.getBytes(),0,str.getBytes().length);   //  写入文字,并传输过去

        socket.shutdownOutput();        //  刷新缓冲区

        BufferedReader br = new BufferedReader(new InputStreamReader(is));  //  实例化对象。接收服务端发来的文本。字节流转换为字符流
        String str2 = null;
        while ((str2 = br.readLine()) != null){
            System.out.println(str2);
        }

        os.close();     //  关流。顺序是从最近使用过的开始,一级一级往上关。
        is.close();
        socket.close();
    }
}

服务端代码:

public class Ser1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999); //  实例化ServerSocket。客户端与服务端的端口号必须是同一个。
        Socket socket = serverSocket.accept();      //  开启监听。如果有客户端发来消息就接听

        InputStream is = socket.getInputStream();       //  实例化输入输出流
        OutputStream os = socket.getOutputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(is));      //  接收客户端发来的文本。字节流转换为字符流

        String str = null;
        while ((str = br.readLine()) != null){
            System.out.println(str);
        }
        
        String str2 = "神经病";
        os.write(str2.getBytes(),0,str2.getBytes().length);     //  把文本发送回客户端
        socket.shutdownOutput();        //  刷新缓冲区

        br.close();         //  自最近使用过的,一级一级往上关
        os.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

3、案例(二)——传输对象

代码大同小异,无非就是对象流的输出读取罢了。注意的是,创建对象的类要序列化。看代码:

客户端:

public class Demo1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost",9999);

        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        Person p1 = new Person("zs", 18);

        ObjectOutputStream oos = new ObjectOutputStream(os);

        oos.writeObject(p1);
    }
}

服务端:

public class Ser1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();

        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        ObjectInputStream ois = new ObjectInputStream(is);
        Person p1 =(Person) ois.readObject();

        System.out.println(p1);
    }
}

4、案例(三)——多客户端与服务器进行交互——多线程解决方案

前面的都是一个客户端与一个服务端相连接。如果是两个客户端甚至是多个客户端相连接呢?如果还是原来的代码,则会报错,原因是因为服务端那仅有的一条连接被占用了,如果有更多的链接进来,则链接不了,所以解决方案是服务端开启多线程:
在这里插入图片描述

客户端的代码不需要动。主要是服务端的代码还有开启多线程的代码:

多线程的代码(基本还是服务端的代码):

public class MyThread_Service extends Thread {
    private Socket socket;  //  私有化

    public MyThread_Service(Socket socket) {    //  构造方法。把外面的 socket 对象传递到这里面。
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            OutputStream os = socket.getOutputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String str = null;
            while ((str = br.readLine()) != null){
                System.out.println(str);
            }

            String str2 = "神经病";
            os.write(str2.getBytes(),0,str2.getBytes().length);
            socket.shutdownOutput();

            br.close();
            os.close();
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然后就是服务端的代码:

public class Ser1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);

        while (true){
            Socket socket = serverSocket.accept();  //  监听。
            MyThread_Service thread = new MyThread_Service(socket);     //  实例化线程对象。注意,多线程那边的有参构造方法。
            thread.start();     //  开启多线程
        }
    }
}

5、案例(四)——图片上传

代码跟以前 IO 流的大差不差:

客户端代码:

public class Demo1 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost",9999);

        InputStream is = new FileInputStream("1.jpg");  //  读取图片
        OutputStream os = socket.getOutputStream();     // 实例化输出流。为后续传输图片做好准备

        byte[] b = new byte[1024];  //  定义一个缓冲区的数组进行读操作
        int len;

        while ((len = is.read(b)) != -1){
            os.write(b,0,len );         //  写。图片传输
        }

        socket.shutdownOutput();        //  刷新输出流
        socket.close();
        os.close();
        is.close();
    }
}

服务端代码:

public class Ser1 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();

        InputStream is = socket.getInputStream();   //  实例化输入流对象

        File f = new File("D:\\");      //  定义好文件路径。准备把图片保存到这个目录

        if (!f.exists()){       //  如果这个路径的目录不存在,则创建。包括多层父目录
            f.mkdirs();
        }

        long time = System.currentTimeMillis();     //  获取系统当前时间(精确到毫秒)
        String FileName = time+".jpg";          //  以当前时间命名文件名字(防止上传的图片重名,重名会覆盖文件)

        OutputStream os = new FileOutputStream(new File(f, FileName));  //  实例化输出流。

        byte[] b = new byte[1024];
        int len;
        while ((len = is.read(b)) != -1){
            os.write(b, 0, len);        //  把图片储存到相关路径
        }

        os.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

四、基于UDP协议传输

此类表示用来发送和接收数据报包的套接字。

UDP:面向无连接的协议,传输的效率高,会丢失数据(短信群发)。

1、构造方法

在这里插入图片描述

2、常用方法

在这里插入图片描述

3、案例(一)——传输简单的文本

客户端代码:

public class Demo1 {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = new DatagramSocket();   //  实例化

        String str = "这里是客户端,你呢";   //  传输文本
        byte[] b = str.getBytes();

        InetAddress address = InetAddress.getByName("localhost");   //  获取本机的IP地址

        DatagramPacket dp = new DatagramPacket(b, 0,b.length,address,9999);   // 创建一个包裹对象。(参数就不说明了,跟前面 IO 流和 TCP 的差不多。

        socket.send(dp);        //  发送
    }
}

服务端:

public class Ser1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(9999);   //  实例化对象。
        byte[] b = new byte[1024];
        DatagramPacket dp = new DatagramPacket(b,0,b.length);   //  构建一个空的包裹

        socket.receive(dp);     //  接收包裹并把里面的数据存到包裹对象当中
        System.out.println(new String(dp.getData(),0,dp.getData().length));     //  打印数据
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值