Java基础之网络编程(二)(下)

简介: 前言文本已收录至我的GitHub仓库,欢迎Star:github.com/bin39232820…种一棵树最好的时间是十年前,其次是现在

数据互发

  • Send
package com.atguigu.ct.producer.Test.AA;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/*
 *发送端
 * 1,创建DatagramSocket对象
 * 2,创建DatagramPacket对象,并封装数据
 * 3,发送数据
 * 4,释放流资源
 */
public class UDPSend {
    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {
        //这个是发送的线程
        new Thread(()->{  Scanner sc = new Scanner(System.in);
            boolean b = true;
            DatagramSocket ds= null;
            while(b){
                String next = sc.next();
                byte[] data = next.getBytes();
                InetAddress inet;
                try {
                    inet = InetAddress.getByName("10.0.142.9");
                    DatagramPacket dp = new DatagramPacket(data, data.length,inet,6666);
                    ds = new DatagramSocket();
                    ds.send(dp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }}).start();
        //这个是接收的线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 接受
                DatagramSocket ds;
                try {
                    ds = new DatagramSocket(6667);
                    byte[] bytes = new byte[1024 * 64];
                    boolean b = true;
                    while (b) {
                        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                        ds.receive(dp);
                        // 拆包
                        // ip , 端口号 , 数据
                        String ip = dp.getAddress().getHostAddress();
                        int port = dp.getPort();
                        int len = dp.getLength();
                        System.out.println(ip + " : " + port + "\t" + new String(bytes, 0, len));
                    }
                    // ds.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
复制代码


  • Receive
package com.atguigu.ct.producer.Test.AA;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
/*
 * UDP接收端
 *
 * 1,创建DatagramSocket对象
 * 2,创建DatagramPacket对象
 * 3,接收数据存储到DatagramPacket对象中
 * 4,获取DatagramPacket对象的内容
 * 5,释放流资源
 */
public class UDPReceive {
    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {
        //接收线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 接受
                DatagramSocket ds;
                try {
                    ds = new DatagramSocket(6666);
                    byte[] bytes = new byte[1024*64];
                    boolean b = true;
                    while(b){
                        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
                        ds.receive(dp);
                        // 拆包
                        //  ip , 端口号  , 数据
                        String ip = dp.getAddress().getHostAddress();
                        int port = dp.getPort();
                        int len = dp.getLength();
                        System.out.println(ip +" : "+port +"\t"+ new String(bytes, 0, len));
                    }
                    //        ds.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //发送线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                Scanner sc = new Scanner(System.in);
                boolean b = true;
                DatagramSocket ds= null;
                while(b){
                    String next = sc.next();
                    byte[] data = next.getBytes();
                    InetAddress inet;
                    try {
                        inet = InetAddress.getByName("10.0.142.9");
                        DatagramPacket dp = new DatagramPacket(data, data.length,inet,6667);
                        ds = new DatagramSocket();
                        ds.send(dp);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}
复制代码


一个就是用while实现了多个线程的数据互发,还有一个就是发送方的端口是随机的,如果不指定的话


TCP通信


TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象

区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据

而TCP通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接

在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端

通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接开始通信

ServerSocket

在开发TCP程序时,首先需要创建服务器端程序。JDK的java.net包中提供了一个ServerSocket类,该类的实例对象可以实现一个服务器段的程序。通过查阅API文档可知,ServerSocket类提供了多种构造方法,接下来就对ServerSocket的构造方法进行逐一地讲解


使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上(参数port就是端口号)

接下来学习一下ServerSocket的常用方法,如表所示


ServerSocket对象负责监听某台计算机的某个端口号,在创建ServerSocket对象后,需要继续调用该对象的accept()方法,接收来自客户端的请求。当执行了accept()方法之后,服务器端程序会发生阻塞,直到客户端发出连接请求,accept()方法才会返回一个Scoket对象用于和客户端实现通信,程序才能继续向下执行


Socket

讲解了ServerSocket对象可以实现服务端程序,但只实现服务器端程序还不能完成通信,此时还需要一个客户端程序与之交互,为此JDK提供了一个Socket类,用于实现TCP客户端程序

Socket类同样提供了多种构造方法,接下来就对Socket的常用构造方法进行详细讲解


使用该构造方法在创建Socket对象时,会根据参数去连接在指定地址和端口上运行的服务器程序,其中参数host接收的是一个字符串类型的IP地址


该方法在使用上与第二个构造方法类似,参数address用于接收一个InetAddress类型的对象,该对象用于封装一个IP地址

在以上Socket的构造方法中,最常用的是第一个构造方法

接下来学习一下Socket的常用方法,如表所示


在Socket类的常用方法中,getInputStream()和getOutStream()方法分别用于获取输入流和输出流。当客户端和服务端建立连接后,数据是以IO流的形式进行交互的,从而实现通信

接下来通过一张图来描述服务器端和客户端的数据传输,如下图所示


简单的TCP网络程序

了解了ServerSocket、Socket类的基本用法,为了让大家更好地掌握这两个类的使用,接下来通过一个TCP通信的案例来进一步学习

要实现TCP通信需要创建一个服务器端程序和一个客户端程序,为了保证数据传输的安全性,首先需要实现服务器端程序

  • TCP 服务器端


/*
 * TCP 服务器端
 *
 * 1,创建服务器ServerSocket对象(指定服务器端口号)
 * 2,开启服务器了,等待客户端的连接,当客户端连接后,可以获取到连接服务器的客户端Socket对象
 * 3,给客户端反馈信息
 * 4,关闭流资源
 */
public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1,创建服务器ServerSocket对象(指定服务器端口号)
        ServerSocket ss = new ServerSocket(6789);
        //2,开启服务器了,等待客户端的连接,当客户端连接后,可以获取到连接服务器的客户端Socket对象
        Socket s = ss.accept();
        //3,给客户端反馈信息
        /*
         * a,获取客户端的输出流
         * b,在服务端端,通过客户端的输出流写数据给客户端
         */
        //a,获取客户端的输出流
        OutputStream out = s.getOutputStream();
        //b,在服务端端,通过客户端的输出流写数据给客户端
        out.write("你已经连接上了服务器".getBytes());
        //4,关闭流资源
        out.close();
        s.close();
        //ss.close();  服务器流 通常都是不关闭的
    }
}
复制代码


  • TCP 客户端
/*
 * TCP 客户端
 *
 * 1,创建客户端Socket对象,(指定要连接的服务器地址与端口号)
 * 2,获取服务器端的反馈回来的信息
 * 3,关闭流资源
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {
        //1,创建客户端Socket对象,(指定要连接的服务器地址与端口号)
        Socket s = new Socket("10.0.142.9", 6789);
        //2,获取服务器端的反馈回来的信息
        InputStream in = s.getInputStream();
        //获取获取流中的数据
        byte[] buffer = new byte[1024];
        //把流中的数据存储到数组中,并记录读取字节的个数
        int length = in.read(buffer);
        //显示数据
        System.out.println( new String(buffer, 0 , length) );
        //3,关闭流资源
        in.close();
        s.close();
    }
}
复制代码


需要注意的是 首先必須开启服务端,不然会连不上的。


IO流和网络编程综合练习(聊天室)


  • 服务器
public class Server2 {
    Socket socket = null;
    boolean flag = true;
    public void run() throws Exception{
        //创建服务器socket对象
        ServerSocket ss = new ServerSocket(12343);
        while(flag){
            //获取socket
            socket = ss.accept();
            //写
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //获取输出流
                    try {
                        Scanner sc = new Scanner(System.in);
                        OutputStream os = socket.getOutputStream();
                        while(true){
                            String data = sc.nextLine();
                            os.write(data.getBytes());
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //读
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 获取输入流
                    try {
                        InputStream is = socket.getInputStream();
                        //一行一行读,设置编码
                        BufferedReader bd = new BufferedReader(new InputStreamReader(is, "utf-8"));
                        String data = null;
                        while((data = bd.readLine())!= null){
                            //明确是谁发送过来的(获取ip)
                            System.out.println(socket.getInetAddress().getHostAddress()+"客户端发送到服务器 : "+data);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        ss.close();
    }
    public static void main(String[] args) throws Exception {
        Server2 server2 = new Server2();
        server2.run();
    }
}
复制代码


  • 客户端
public class Client2 {
    public static void main(String[] args) throws Exception {
        //创建客户端socket对象
        Socket socket = new Socket("127.0.0.1",12343);
        //获取输入流
        final InputStream is = socket.getInputStream();
        //一行一行读。设置编码格式
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while(true){
                        byte[] by = new byte[1024];
                        int len = is.read(by);
                        System.out.println("服务器返回数据 : "+new String(by,0,len));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //获取输出流
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw =  new BufferedWriter(new OutputStreamWriter(os,"utf-8"));
        Scanner sc = new Scanner(System.in);
        boolean flag = true;
        while(flag){
            String data = sc.nextLine();
            bw.write(data);
            bw.newLine();
            bw.flush();
        }
        is.close();
        os.close();
        socket.close();
    }
}
复制代码



知识点总结


  • IP地址:用来唯一表示我们自己的电脑的,是一个网络标示
  • 端口号: 用来区别当前电脑中的应用程序的
  • UDP: 传送速度快,但是容易丢数据,如视频聊天
  • TCP: 传送稳定,不会丢失数据,如文件的上传、下载
  • UDP程序交互的流程
  • 发送端
1,创建DatagramSocket对象
    2,创建DatagramPacket对象,并封装数据
    3,发送数据
    4,释放流资源
复制代码


  • 接收端
1,创建DatagramSocket对象
    2,创建DatagramPacket对象
    3,接收数据存储到DatagramPacket对象中
    4,获取DatagramPacket对象的内容
    5,释放流资源
复制代码


  • TCP程序交互的流程
  • 客户端
1,创建客户端的Socket对象
    2,获取Socket的输出流对象
    3,写数据给服务器
    4,获取Socket的输入流对象
    5,使用输入流,读反馈信息
    6,关闭流资源
复制代码


  • 服务器端
1,创建服务器端ServerSocket对象,指定服务器端端口号
    2,开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
    3,通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
    4,通过客户端的输入流,获取流中的数据
    5,通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
    6,通过客户端的输出流,写数据到流中
    7,关闭流资源
复制代码


结尾


网络编程基础就讲这么多了,大家可以操作一下试试,下面的打算讲讲多线程,锁咯

相关文章
|
3月前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
87 11
|
2天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
46 23
|
4月前
|
Java 程序员
JAVA程序员的进阶之路:掌握URL与URLConnection,轻松玩转网络资源!
在Java编程中,网络资源的获取与处理至关重要。本文介绍了如何使用URL与URLConnection高效、准确地获取网络资源。首先,通过`java.net.URL`类定位网络资源;其次,利用`URLConnection`类实现资源的读取与写入。文章还提供了最佳实践,包括异常处理、连接池、超时设置和请求头与响应头的合理配置,帮助Java程序员提升技能,应对复杂网络编程场景。
101 9
|
4月前
|
人工智能 Java 物联网
JAVA网络编程的未来:URL与URLConnection的无限可能,你准备好了吗?
随着技术的发展和互联网的普及,JAVA网络编程迎来新的机遇。本文通过案例分析,探讨URL与URLConnection在智能API调用和实时数据流处理中的关键作用,展望其未来趋势和潜力。
76 7
|
1月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
20天前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
|
4月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
83 13
|
4月前
|
Java 开发者
JAVA高手必备:URL与URLConnection,解锁网络资源的终极秘籍!
在Java网络编程中,URL和URLConnection是两大关键技术,能够帮助开发者轻松处理网络资源。本文通过两个案例,深入解析了如何使用URL和URLConnection从网站抓取数据和发送POST请求上传数据,助力你成为真正的JAVA高手。
108 11
|
4月前
|
安全 Java API
深入探索Java网络编程中的HttpURLConnection:从基础到进阶
本文介绍了Java网络编程中HttpURLConnection的高级特性,包括灵活使用不同HTTP方法、处理重定向、管理Cookie、优化安全性以及处理大文件上传和下载。通过解答五个常见问题,帮助开发者提升网络编程的效率和安全性。
250 9
|
4月前
|
JSON 安全 算法
JAVA网络编程中的URL与URLConnection:那些你不知道的秘密!
在Java网络编程中,URL与URLConnection是连接网络资源的两大基石。本文通过问题解答形式,揭示了它们的深层秘密,包括特殊字符处理、请求头设置、响应体读取、支持的HTTP方法及性能优化技巧,帮助你掌握高效、安全的网络编程技能。
137 9

热门文章

最新文章