首页 > 编程语言 >Java基础——网络编程

Java基础——网络编程

时间:2024-12-04 18:58:04浏览次数:10  
标签:Java socket java 编程 网络 import close new 客户端

一、网络基础

  1. 网络通信:
    1. 网络通信的概念:两台设备之间通过网络实现数据传输
    2. 网络通信:将数据通过网络从一台设备传输到另一台设备
    3. java.net包下提供了一系列的类和接口,供程序员使用,完成网络通信
  2. 网络:
    1. 概念:两台或多台设备通过一定的物理设备连接起来构成了网络
    2. 根据网络的覆盖范围不同,对网络进行分类:(1)局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房或一个公司(2)城域网:覆盖范围较大,可以覆盖一个城市(3)广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广域网的代表
  3. ip地址:
    1. 概念:用于唯一标识网络中的每台主机/计算机
    2. 查看ip地址:ipconfig
    3. ip地址的表示形式:点分十进制 xx.xx.xx.xx
    4. 每一个十进制数的范围0~255
    5. ip地址的组成=网络地址+主机地址,比如:192.168.16.69(192.168.16代表网络地址)
    6. IPv6是用于替代IPv4的下一代IP协议,其地址数量号称可以为世界上的每一粒沙子编上一个地址
    7. 由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
    8. IPv6使用128位(16个字节)表示一个地址。xx:xx:xx:xx:xx:xx:xx:xx(每个xx代表两个字节)
    9. IPv4地址分类(1)A类地址:1个字节代表网络号(网络号第一位固定为0),3个字节代表主机号(2)B类地址:2个字节代表网络号(网络号前两位固定为10),2个字节代表主机号(3)C类地址:3个字节代表网络号(网络号前三位固定为110),1个字节代表主机号(4)暂时不关注比较特殊的D类和E类地址(5)127.0.0.1表示本机地址
    10. 地址的表示范围(第一个字节)(1)A类地址:0~127(2的7次方-1,因为有一位是固定的)(2)B类地址:128~191(B类地址是从128开始,128+0~128+63,2的6次方-1等于63)(3)C类地址:192~223(C类地址是从192开始,192+0~192+31,2的5次方-1等于31)
  4. 域名:
    1. www.baidu.com
    2. 好处:为了方便记忆,解决记ip地址的困难
    3. 概念:将ip地址映射成域名
  5. 端口号:
    1. 概念:用于标识计算机上某个特定的网络程序(一个电脑上可以同时运行多个服务)
    2. 表示形式:以整数形式,范围0~65535(同一个主机上两个不同的服务不能占用相同的端口)(两个字节表示端口,2的16次方-1就是65535)
    3. 0~1024已经被占用,比如ssh 22,ftp 21,smtp 25,http 80。因此,在网络开发中,不要使用0~1024的端口
    4. 常见的网络程序端口号:(1)Tomcat 8080(2)mysql 3306(3)oracle 1521(4)sqlserver 1433
  6. 网络协议:
    1. 举例理解协议这个概念:人和人交流通过语言,语言本身就是一种协议
    2. 在网络编程中,数据的组织形式就是协议
    3. TCP/IP协议(Transmission Control Protocol/Internet Protocol),中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是Internet最基本的协议。简单地说,它就是由网络层的IP协议和传输层的TCP协议组成的
    4. 网络通信协议:
      OSI模型TCP/IP模型TCP/IP模型各层对应的协议
      应用层应用层HTTP、ftp、telnet、DNS...
      表示层
      会话层
      传输层传输层(TCP)TCP、UDP...
      网络层网络层(IP)IP、ICMP、ARP...
      数据链路层物理层+数据链路层Link
      物理层
  7. TCP协议(传输层):
    1. 使用TCP协议前,需要先建立TCP连接,形成传输数据通道
    2. 传输前,采用“三次握手”方式。是可靠的(三次握手理解:(1)A跟B说了一句话(2)A需要知道自己说的话是否被B听到,所以B回了A一句(3)B需要知道自己说的话是否被A听到,因此A还要回B一句话)
    3. TCP协议进行通信的两个应用进程:客户端、服务端
    4. 在连接中可进行大数据量的传输
    5. 传输完毕,需要释放已经建立的连接,效率低
  8. UDP协议(传输层):
    1. 将数据、源、目的封装成数据包,不需要建立连接
    2. 每个数据报的大小限制在64K内,不适合传输大量的数据
    3. 因无需建立连接,故是不可靠的
    4. 发送数据结束时,无需释放资源(因为没有建立连接),速度快

二、InetAddress

  1. InetAddress类的常用方法:
    getLocalHost获取本机的InetAddress对象
    getByName根据指定的主机名/域名获取InetAddress对象
    getHostName

    获得InetAddress对象的主机名

    getHostAddress获得InetAddress对象的地址
  2. 应用案例演示:
    package com.study;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    //演示InetAddress类的使用
    public class API_ {
        public static void main(String[] args) throws UnknownHostException {
            //1.获取本机的InetAddress对象
            InetAddress localHost = InetAddress.getLocalHost();
            //可以获取到     本机的主机名/本机的ip地址
            System.out.println(localHost);
    
            //2.根据指定的主机名,获取InetAddress对象
            InetAddress localHost2 = InetAddress.getByName("这里填写自己的主机名");
            //localHost2和localHost的输出结果一样
            System.out.println(localHost2);
    
            //3.根据域名返回InetAddress对象
            InetAddress host = InetAddress.getByName("www.baidu.com");
            //可以获取到     域名/ip地址
            System.out.println(host);
    
            //4.通过一个InetAddress对象,获取它对应的ip地址
            String ipAddress = localHost2.getHostAddress();
            System.out.println(ipAddress);
    
            //5.通过一个InetAddress对象,获取它对应的主机名或者是域名
            String name = localHost2.getHostName();
            System.out.println(name);
        }
    }
  3. 这些API的作用(1)获取本机的信息【主机名/IP】(2)通过域名获取远程服务器的【域名/IP】

三、Socket

  1. Socket的基本介绍:
    1. 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准
    2. 通信的两端都要有Socket,是两台机器间通信的端点
    3. 网络通信实际上就是Socket之间的通信
    4. Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
    5. 一般主动发起通信的应用程序称为客户端,等待请求通信的为服务端
  2. 示意图:
  3. 当我们需要通讯时(读写数据):
    1. socket.getOutputStream()
    2. socket.getInputStream()
  4. 客户端和服务器在通常情况下,是在不同主机的。但在我们学习该部分知识时,客户端和服务器在一台主机

四、TCP编程

(1)TCP网络通信编程基本介绍

  1. 基于客户端——服务端的网络通信

  2. 底层使用的是TCP/IP协议

  3. 应用场景举例:客户端发送数据,服务端接收并显示在控制台

  4. 基于Socket的TCP编程

(2)TCP网络通信编程

  1. 应用案例1演示(使用字节流)(1)编写一个客户端和一个服务器端(2)服务器端在9999端口监听(注意:当没有客户端连接9999端口时,程序会阻塞,等待连接)(3)客户端连接到服务器端,发送“hello,server”,然后退出(4)服务器端接收到客户端发送的信息,输出,并退出
    //服务端代码
    package com.study.socket;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketTCP01Server {
        public static void main(String[] args) throws IOException {
            //1.在本机的9999端口监听,等待连接
            //一定要确保本机没有其它服务占用9999端口
            ServerSocket serverSocket = new ServerSocket(9999);
    
            //2.当没有客户端连接9999端口时,程序会阻塞,等待连接
            //如果有客户端连接,则会返回Socket对象,程序继续往下执行
            //这个socket就是服务器的socket
            Socket socket = serverSocket.accept();
    
            //3.通过输入流,读取客户端写入到数据通道的数据,并在控制台显示
            InputStream inputStream = socket.getInputStream();
    
            //4.因为不是BufferedInputStream,所以我们要自己设置缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read(b)) != -1){
                System.out.print(new String(b,0,readLen));//根据读取到的实际长度显示内容
            }
    
            //5.关闭流和Socket
            inputStream.close();
            socket.close();
    
            //6.服务器端还要多关闭一个ServerSocket
            serverSocket.close();
        }
    }
    //客户端代码
    package com.study.socket;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class SocketTCP01Client {
        public static void main(String[] args) throws IOException {
            //1.连接服务器(ip,端口)
            //因为目前服务器在本机,所以InetAddress.getLocalHost().getHostAddress()
            //这个socket就是客户端的socket
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),9999);
    
            //2.连接上后,获得输出流对象。该输出流对象是与该socket关联的
            OutputStream outputStream = socket.getOutputStream();
    
            //3.通过输出流对象,将数据写入数据通道
            outputStream.write("hello,server".getBytes());
    
            //4.必须关闭流对象和socket
            outputStream.close();
            socket.close();
        }
    }

  2. 细节:服务器端的ServerSocket每接收到一个连接请求,就会生成一个socket(服务器端的)
  3. 应用案例2演示(使用字节流)(1)编写一个服务器端和一个客户端(2)服务器端在9999端口监听(3)客户端连接到服务器端,发送“hello,server”,并接收服务器端回发的“hello,client”,再退出(4)服务器端接收到客户端发送的信息,输出,并向客户端发送“hello,client”,再退出
    //服务器代码
    package com.study.socket;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketTCP02Server {
        public static void main(String[] args) throws IOException {
            //1.服务器端在9999端口监听
            ServerSocket serverSocket = new ServerSocket(9999);
            //2.服务器端阻塞,等待客户端发来连接。服务器端接收到连接,才会生成自己的Socket对象
            System.out.println("服务端在9999端口监听,等待连接...");
            Socket socket = serverSocket.accept();
    
            //客户端给服务端发
            //3.服务器读取客户端在数据通道上写的数据,并显示
            InputStream inputStream = socket.getInputStream();
            //因为不是BufferedInputStream,所以要自己设置缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read(b)) != -1){
                System.out.println(new String(b,0,readLen));//读多少数据写多少数据
            }
    
            //服务端给客户端发
            //4.服务器向客户端回发"hello,client"。先获得字节输出流,再将数据写入数据通道
            OutputStream outputStream = socket.getOutputStream();
            //因为是字节输出流,所以要将字符串转为字节数组输出
            outputStream.write("hello,client".getBytes());
    
            //设置写入结束标记!!!
            socket.shutdownOutput();
    
            //5.关闭输入流输出流和两个socket
            inputStream.close();
            outputStream.close();
            socket.close();
            //服务器要多关闭一个
            serverSocket.close();
            System.out.println("服务器退出...");
        }
    }
    //客户端代码
    package com.study.socket;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class SocketTCP02Client {
        public static void main(String[] args) throws IOException {
            //1.客户端和服务器端建立连接
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),9999);
    
            //客户端给服务端发
            //2.客户端向服务端发送"hello,server"。先获得字节输出流,再将数据写入数据通道
            OutputStream outputStream = socket.getOutputStream();
            //因为是字节输出流,所以要将字符串转为字节数组输出
            outputStream.write("hello,server".getBytes());
    
            //设置写入结束标记!!!
            socket.shutdownOutput();
    
    
            //服务端给客户端发
            //3.客户端读取服务器在数据通道上写的数据,并显示
            InputStream inputStream = socket.getInputStream();
            //因为不是BufferedInputStream,所以要自己设置缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read(b)) != -1){
                System.out.println(new String(b, 0, readLen));
            }
    
            //4.关闭输出流和输入流还有socket
            outputStream.close();
            inputStream.close();
            socket.close();
            System.out.println("客户端退出");
        }
    }

  4. 注意:服务器在输出客户端发来的“hello,server”后,不知道什么时候自己才能往数据通道数据,因此会阻塞。所以客户端在发完“hello,server”,服务器在发完“hello,client”后,都要设置结束标记,才能避免此类问题!这样,服务器就知道客户端已经写完了,自己可以写了。设置结束标记的方法:socket.shutdownOutput();
  5. 应用案例3(使用字符流)(1)编写一个服务端和一个客户端(2)服务端在9999端口监听(3)客户端连接到服务端,发送“hello,server”,并接收服务端回发的“hello,client”,再退出(4)服务端接收到客户端发送的信息,输出,并发送"hello,client",再退出
    //服务器代码
    package com.study.socket;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketTCP03Server {
        public static void main(String[] args) throws IOException {
            //1.服务器在9999端口监听
            ServerSocket serverSocket = new ServerSocket(9999);
            //2.服务端阻塞,等待客户端请求连接。一旦收到连接请求,就得到一个Socket对象
            System.out.println("服务器在9999端口监听,等待连接...");
            Socket socket = serverSocket.accept();
    
            //客户端给服务器发
            //3.服务器通过socket得到输入流,用输入流从数据通道读取数据
            //因为题目要求用字符流处理问题,所以我们用到转换流和包装流
            InputStream inputStream = socket.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            //由于客户端用writer.newLine()设置结束标记,所以我们只能用readLine读取数据
            String line = bufferedReader.readLine();
            System.out.println(line);
    
            //服务器给客户端发
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write("hello,client");
            bufferedWriter.newLine();
            bufferedWriter.flush();
    
            //关流
            bufferedReader.close();
            bufferedWriter.close();
            socket.close();
            serverSocket.close();
            System.out.println("服务器退出...");
        }
    }
    //客户端代码
    package com.study.socket;
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class SocketTCP03Client {
        public static void main(String[] args) throws IOException {
            //1.客户端向服务端建立连接(IP+端口)
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),9999);
    
            //客户端给服务器发
            //2.客户端通过socket得到输出流,用输出流向数据通道写入数据,写完了别忘记设置结束标记!
            //如果我们想用字符流处理问题,就要用到转换流将字节流转成字符流,还要用到包装流,将它包装为BufferedWriter
            OutputStream outputStream = socket.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            //用该包装流写入数据
            bufferedWriter.write("hello,server");
            //结束标记socket.shutdownOutput();,或者如下
            bufferedWriter.newLine();
            //写完数据要刷新!!!这样才能真正写进去,这里不用关闭是因为关闭放在最后一部分!!!
            bufferedWriter.flush();
    
            //服务器给客户端发
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = bufferedReader.readLine();
            System.out.println(line);
    
            //关流
            bufferedReader.close();
            bufferedWriter.close();
            socket.close();
            System.out.println("客户端退出");
        }
    }

  6. 使用字节流和使用字符流进行网络通信编程的区别:(1)使用字符流,需要先用socket得到字节流,再将字节流转换成字符流,最后将其包装成BufferedWriter/BufferedReader(2)字符流设置结束标记的方式:除了socket.shutdownOutput();,还有writer.newLine();。如果使用后者,那么对方必须用readLine读取数据(3)注意!!!一定要先newline,再flush

(3) 网络上传文件

  1. 应用案例演示4(1)编写一个服务端,和一个客户端(2)服务器端在8888端口监听(3)客户端连接到服务端,发送一张D盘下的图片(4)服务器端接收到客户端发送的图片,保存到src下,发送“收到图片”,再退出(5)客户端接收到服务端发送的“收到图片”,再退出
    //服务器代码
    package com.study.socket;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class SocketTCP04Server {
        public static void main(String[] args) throws IOException {
            //服务器在8888端口监听
            ServerSocket serverSocket = new ServerSocket(8888);
            //等待客户端连接
            System.out.println("服务器在8888端口监听,等待连接...");
            Socket socket = serverSocket.accept();
            //读取数据通道的dog.jpg,并将它写入src下
            InputStream inputStream = socket.getInputStream();
            String filePath = "src\\dog.jpg";
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
            //建立缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen=inputStream.read(b))!=-1){
                bufferedOutputStream.write(b,0,readLen);
            }
            //服务器向客户端发送"收到图片"
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write("收到图片");
            bufferedWriter.newLine();
            bufferedWriter.flush();
            //退出
            inputStream.close();
            bufferedOutputStream.close();
            bufferedWriter.close();
            socket.close();
            serverSocket.close();
            System.out.println("服务器退出...");
        }
    }
    //客户端代码
    package com.study.socket;
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;
    
    @SuppressWarnings("ALL")
    public class SocketTCP04Client {
        public static void main(String[] args) throws IOException {
            //与服务端建立连接
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),8888);
            //将D盘下的dog.jpg写入数据通道
            String filePath = "D:\\dog.jpg";
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
            OutputStream outputStream = socket.getOutputStream();
            //建立缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            //相当于读到客户端
            while((readLen=bufferedInputStream.read(b))!=-1){
                outputStream.write(b,0,readLen);//读多少写多少
            }
            //设置结束标记
            socket.shutdownOutput();
            //客户端接收到服务端发送的“收到图片”
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = bufferedReader.readLine();
            System.out.println(line);
            //退出
            bufferedInputStream.close();
            outputStream.close();
            bufferedReader.close();
            socket.close();
            System.out.println("客户端退出...");
        }
    }

  2. 总结:(1)如果与数据通道相关,从数据通道读取数据InputStream inputStream = socket.getInputStream();,向数据通道写入数据OutputStream outputStream = socket.getOutputStream();(2)在此基础上,如果我们需要使用字符流来操作,那么我们就用转换流和包装流(3)与数据通道无关的,我们可以参考IO流

(4)netstat指令

  1. netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
    1. Listening表示某个端口在监听
    2. 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息(Established)
    3. Ctrl+C可以退出该指令
  2. netstat -an|more可以分页显示,翻页:在光标闪烁处输入空格键
  3. 要求在dos控制台下执行
  4. 如果想知道是哪个程序在监听此端口,那么(要以管理员身份运行):netstat -anb
  5. 如果是上面应用案例演示的代码,那么8888端口就是被java.exe监听

(5) TCP连接秘密

  1. 当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个客户端的端口是随机的,是TCP/IP来分配的
  2. 当TCP连接被释放后,客户端的端口就会被释放

五、UDP编程

(1)UDP网络通信编程基本介绍

  1. 类DatagramSocket和类DatagramPacket实现了基于UDP协议的网络通信
  2. UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能安全送到目的地,也不能确定什么时候可以抵达
  3. DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号,以及接收端的IP地址和端口号
  4. UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接

(2)UDP网络通信编程

  1. 基本流程:
    1. 核心的两个类/对象:DatagramSocket(接收端指定在哪个端口接收数据/发送端指定在哪个端口发送数据),DatagramPacket(接收端需要创建,用来接收发送端发来的DatagramPacket对象;发送端也需要创建,把需要发送的数据放进DatagramPacket对象)
    2. 建立发送端、接收端,二者可以随时转换,即发送端当接收来自接收端的数据时,它又可以成为接收端(没有服务端和客户端概念)
    3. 发送数据前,建立数据报 DatagramPacket对象
    4. 调用DatagramSocket的发送、接收方法(socket.receive(接收端创建的DatagramPacket对象),socket.send(发送端创建的DatagramPacket对象))
    5. 关闭DatagramSocket
  2. UDP说明:
    1. 没有明确的服务端和客户端,演变成发送端和接收端
    2. 接收数据和发送数据是通过DatagramSocket对象完成
    3. 将数据封装到DatagramPacket对象(装包),发送
    4. 当接收到在网络上传送的DatagramPacket对象时,需要进行拆包,取出数据
    5. DatagramSocket指定在哪个端口接收数据
  3. 应用案例演示(1)编写一个接收端A,和一个发送端B(2)接收端A在9999端口等待接收数据(3)发送端B向接收端A发送数据“hello,明天吃火锅~”(4)接收端A接收到发送端B发送的数据,回复“好的,明天见”,再退出(5)发送端B接收到回复的数据,再退出
    //接收端A的代码
    package com.study.UDP;
    
    import java.io.IOException;
    import java.net.*;
    
    public class UDPReceiverA {
        public static void main(String[] args) throws IOException {
            //1.创建一个DatagramSocket对象,准备在9999端口接收数据
            DatagramSocket socket = new DatagramSocket(9999);
            //2.构建一个DatagramPacket对象,准备接收数据
            //UDP协议中,每个数据报最大是64K
            byte[] b = new byte[1024];
            DatagramPacket packet = new DatagramPacket(b, b.length);
            //3.调用接收方法。将通过网络传输的DatagramPacket对象,填充到这里的packet对象
            //如果没有数据发送到9999端口,就会阻塞等待
            System.out.println("接收端A等待接收数据...");
            socket.receive(packet);
            //4.把packet进行拆包,取出数据并显示
            int length = packet.getLength();//实际接收到的数据字节长度
            byte[] data = packet.getData();//实际接收到的数据
            System.out.println(new String(b, 0, length));
            //5.接收端A向发送端B回复信息"好的,明天见"
            byte[] info = "好的,明天见".getBytes();
            DatagramPacket packet2 = new DatagramPacket(info,info.length, InetAddress.getLocalHost(),9998);
            socket.send(packet2);
    
            //6.关闭资源socket
            socket.close();
            System.out.println("A端退出");
        }
    }
    package com.study.UDP;
    
    import java.io.IOException;
    import java.net.*;
    
    public class UDPSenderB {
        public static void main(String[] args) throws IOException {
            //1.创建DatagramSocket对象,准备在9998发送数据
            DatagramSocket socket = new DatagramSocket(9998);
            //2.将需要发送的数据封装到DatagramPacket(数据,数据的长度,接收端ip,接收端端口)
            byte[] info = "hello,明天吃火锅~".getBytes();
            DatagramPacket packet = new DatagramPacket(info, info.length, InetAddress.getLocalHost(),9999);
            //3.发送DatagramPacket对象
            socket.send(packet);
            //4.发送端接收接收端回复的信息"好的,明天见"
            byte[] b = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(b,b.length);
            System.out.println("发送端B等待接收数据...");
            socket.receive(packet2);
            int length = packet2.getLength();
            byte[] data = packet2.getData();
            System.out.println(new String(data, 0, length));
    
            //关闭资源
            socket.close();
            System.out.println("B端退出");
        }
    }

  4. 此时使用netstat -an命令,可以看到UDP的9999端口正在监听
  5. 总结:
    //发送端发送数据的核心代码
    //第一步,设置在哪个端口发送数据(该端口还可以用来接收数据)
    DatagramSocket socket = new DatagramSocket(9998);
    //第二步,将需要发送的数据转成字节数据,放入DatagramPacket对象,并指定要发给哪个ip、端口
    byte[] info = "hello,明天吃火锅~".getBytes();
    DatagramPacket packet = new DatagramPacket(info, info.length, InetAddress.getLocalHost(),9999);
    //第三步,发送DatagramPacket对象
    socket.send(packet);
    //接收端接收数据的核心代码
    //第一步,创建一个合理大小的DatagramPacket对象(数据都是以字节数组的形式保存的)
    byte[] b = new byte[1024];
    DatagramPacket packet = new DatagramPacket(b, b.length);
    //第二步,接收来自发送端的DatagramPacket对象,并将该对象转成自己创建的DatagramPacket对象
    socket.receive(packet);
    //第三步,如果我们需要在屏幕上显示数据
    int length = packet.getLength();//实际接收到的数据字节长度
    byte[] data = packet.getData();//实际接收到的数据
    System.out.println(new String(b, 0, length));

六、网络编程作业

  1. 编程题1(1)使用字符流的方式,编写一个客户端程序和一个服务器端程序(2)客户端发送“name”,服务器端接收到后,返回“我是nova”,nova是你自己的名字(3)客户端发送“hobby”,服务器端接收到后,返回“编写Java程序”(4)不是这两个问题,回复“你说啥呢”
    //服务器端代码
    package com.study.homework;
    
    import java.io.*;
    import java.net.*;
    
    @SuppressWarnings("ALL")
    public class Server_ {
        public static void main(String[] args) throws IOException {
            //1.在本机的9999端口监听,等待连接
            ServerSocket serverSocket = new ServerSocket(9999);
            //2.阻塞等待客户端的连接
            System.out.println("服务器端等待连接...");
            Socket socket = serverSocket.accept();
            //3.服务端接收用户发来的问题,注意题目要求使用字符流
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            //4.因为客户端使用newLine设置结束标记的,因此我们要用readLine读数据
            String line = bufferedReader.readLine();
            String info = "";//要发送给客户端的数据
            //5.根据用户发的问题确定要返回什么信息
            if ("name".equals(line)){
                info = "Tom";
            }else if ("hobby".equals(line)){
                info = "编写Java程序";
            }else{
                info = "你说啥呢";
            }
            //6.将要返回给客户端的数据写进数据通道
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write(info);
            //7.设置结束标记并刷新
            bufferedWriter.newLine();
            bufferedWriter.flush();
            //6.关流,关闭资源
            bufferedWriter.close();
            bufferedReader.close();
            socket.close();
            serverSocket.close();
            System.out.println("服务器端退出...");
        }
    }
    //客户端代码
    package com.study.homework;
    
    import java.io.*;
    import java.net.*;
    import java.util.Scanner;
    
    @SuppressWarnings("ALL")
    public class Client_ {
        public static void main(String[] args) throws IOException {
            //1.向服务器端发起连接
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            //2.接收用户从键盘输入的数据
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入你的问题:");
            String next = scanner.next();
            //3.向服务器端发送用户输入的问题,注意题目要求使用字符流
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write(next);
            //4.注意:要设置结束标记!还要刷新输出流,才能将数据真正写进数据通道
            bufferedWriter.newLine();
            bufferedWriter.flush();
            //5.客户端接收来自服务器端的问题回答
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String info = bufferedReader.readLine();
            System.out.println(info);
            //6.关流,关闭资源
            bufferedWriter.close();
            bufferedReader.close();
            socket.close();
            System.out.println("客户端退出...");
        }
    }

  2.  编程题2(1)编写一个接收端A,和一个发送端B,使用UDP协议完成(2)接收端在8888端口等待接收数据(3)发送端向接收端发送数据“四大名著是哪些”(4)接收端接收到发送端发送的问题后,返回“四大名著是《红楼梦》...”,否则返回what?(5)接收端和发送端程序退出
    //接收端代码
    package com.study.homework;
    
    import java.io.IOException;
    import java.net.*;
    
    @SuppressWarnings("ALL")
    public class Receiver_ {
        public static void main(String[] args) throws IOException {
            //1.接收端在8888端口等待接收数据
            DatagramSocket socket = new DatagramSocket(8888);
            //2.创建一个DatagramPacket对象,用来接收发送端发来的数据,大小暂定为1024
            byte[] b = new byte[1024];
            DatagramPacket packet = new DatagramPacket(b,b.length);
            System.out.println("接收端等待接收问题...");
            //3.接收发送端发来的问题
            socket.receive(packet);
            //4.根据问题内容判断要回复的信息
            String info = "";
            int length = packet.getLength();
            byte[] data = packet.getData();
            String line = new String(data,0,length);
            if ("四大名著是哪些".equals(line)){
                info = "四大名著是《红楼梦》《三国演义》《水浒传》《西游记》";
            }else{
                info = "what?";
            }
            //5.将要回复的信息放在DatagramPacket对象,并发送给发送端
            byte[] answer = info.getBytes();
            DatagramPacket packet2 = new DatagramPacket(answer,answer.length,InetAddress.getLocalHost(),9999);
            socket.send(packet2);
            //6.关闭资源
            socket.close();
            System.out.println("接收端退出...");
        }
    }
    //发送端代码
    package com.study.homework;
    
    import java.io.IOException;
    import java.net.*;
    import java.util.Scanner;
    
    @SuppressWarnings("ALL")
    public class Sender_ {
        public static void main(String[] args) throws IOException {
            //1.发送端在9999端口发送数据
            DatagramSocket socket = new DatagramSocket(9999);
            //2.创建一个扫描器对象,等用户从键盘输入问题
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入你的问题:");
            String next = scanner.next();
            //3.将用户输入的问题放入DatagramPacket对象
            byte[] question = next.getBytes();
            DatagramPacket packet = new DatagramPacket(question,question.length,InetAddress.getLocalHost(),8888);
            //4.将DatagramPacket对象发送给接收端
            socket.send(packet);
            //5.接收接收端发送来的答案,并在屏幕输出
            byte[] b = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(b,b.length);
            socket.receive(packet2);
            int length = packet2.getLength();
            byte[] data = packet2.getData();
            System.out.println(new String(data, 0, length));
            //6.关闭资源
            socket.close();
            System.out.println("发送端退出...");
        }
    }

  3. TCP文件下载(1)编写客户端程序和服务器端程序(2)客户端可以输入一个图片文件名,比如dog,服务端收到图片名后,可以给客户端返回这个图片文件,如果服务器没有这个文件,返回默认的cat.jpg即可(3)客户端收到该文件后,保存到D:\demo02\dog.jpg(文件名指定是这个)
    //服务器端代码
    package com.study.homework02;
    
    import java.io.*;
    import java.net.*;
    
    @SuppressWarnings("ALL")
    public class Server {
        public static void main(String[] args) throws IOException {
            //1.服务器端在9999端口监听,等待客户端的连接
            ServerSocket serverSocket = new ServerSocket(9999);
            //2.服务器等待来自客户端的连接
            System.out.println("服务器等待来自客户端的连接...");
            Socket socket = serverSocket.accept();
            //3.从数据通道读取客户端发来的信息
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            //因为客户端使用newLine来设置结束标记,因此我们用readLine读数据
            String fileName = bufferedReader.readLine();
            //4.根据用户输入的文件名,判断我们要从磁盘中读取哪个文件并写入数据通道
            String srcFilePath = "";
            if("dog".equals(fileName)){
                srcFilePath = "D:\\dog.jpg";
            }else{
                srcFilePath = "D:\\cat.jpg";
            }
            //5.从磁盘读取文件(输入流)并写入数据通道(输出流)
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
            OutputStream outputStream = socket.getOutputStream();//使用的是字节流,因此不需要转换和包装
            //字节流要设置缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen = bufferedInputStream.read(b))!=-1){//已经读到末尾会返回-1
                outputStream.write(b,0,readLen);//读多少,写多少。用数组缓冲都要涉及这个
            }
            //6.TCP往数据通道写完数据,一定要设置结束标记
            socket.shutdownOutput();
            //7.关流关资源
            bufferedReader.close();
            outputStream.close();
            bufferedInputStream.close();
            socket.close();
            serverSocket.close();
            System.out.println("服务器端退出");
        }
    }
    //客户端代码
    package com.study.homework02;
    
    import java.io.*;
    import java.net.*;
    import java.util.Scanner;
    
    @SuppressWarnings("ALL")
    public class Client {
        public static void main(String[] args) throws IOException {
            //1.客户端向服务端发起请求连接
            Socket socket = new Socket(InetAddress.getLocalHost(),9999);
            //2.接收用户从键盘输入的信息
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入要下载的图片名:");
            String next = scanner.next();
            //3.将用户输入的信息写进数据通道
            OutputStream outputStream = socket.getOutputStream();
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write(next);
            //4.设置结束标记,并刷新
            bufferedWriter.newLine();
            bufferedWriter.flush();
            //5.从数据通道读取文件并将它写入目标位置
            String destFilePath = "D:\\demo02\\dog.jpg";
            InputStream inputStream = socket.getInputStream();//字节流,因此不需要转换和包装
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));//包装流就是对节点流进行包装
            //设置缓冲
            byte[] b = new byte[1024];
            int readLen = 0;
            while((readLen = inputStream.read(b))!=-1){
                bufferedOutputStream.write(b,0,readLen);
            }
            //6.关流关资源
            bufferedWriter.close();
            inputStream.close();
            bufferedOutputStream.close();
            socket.close();
            System.out.println("下载成功!");
            System.out.println("客户端退出...");
        }
    }
    

本笔记根据韩顺平零基础学Java课程学习整理而来  

标签:Java,socket,java,编程,网络,import,close,new,客户端
From: https://blog.csdn.net/weixin_74019079/article/details/144185872

相关文章

  • JavaWeb:会话_过滤器_监听器
    该笔记根据尚硅谷的JavaWeb课程进行整理 一、会话(1)会话管理概述1.1.1为什么需要会话管理HTTP是无状态协议举例:张三去一家饭馆点了几道菜,觉得味道不错,第二天又去了,对老板说,还点上次的那几道菜无状态:老板没有记录张三是否来过,更没有记录他上次点了哪些菜,张三只能重新......
  • 11.Java 集合(ArrayList、Vector、LinkedList、HashSet、LinkedHashSet、TreeSet、Hash
    一、集合概述1、数组的缺点长度开始时必须指定,且一旦指定,不能更改保存的元素必须为同类型对数组数组元素进行增删较为麻烦2、集合的好处可以动态保存多个任意类型提供了一系列方便操作对象的元素3、集合体系Collection接口:单列集合Map接口:双列集合二......
  • 深入解析Java线程源码:从基础到并发控制的全面指南(一)
    一:Java线程基础和源码解析packagejava.lang;importjava.lang.ref.Reference;importjava.lang.ref.ReferenceQueue;importjava.lang.ref.WeakReference;importjava.security.AccessController;importjava.security.AccessControlContext;importjava.security.Pr......
  • [Linux网络]TCP和UDP协议的底层理论
    目录一、TCP和UDP协议的简单认识1.传输层协议2.五元组二、UDP协议1.UDP协议格式2.UDP协议的特点3.面向数据报4.UDP传输报文在内核中的管理5.基于UDP协议的应用层协议(部分)三、TCP协议1.发送和接收数据示意图2.TCP协议格式3.确认应答机制和超时重传机制4.发......
  • Java中的“接口”补充
    1.在Java中,类和类之间是只可以单继承的,而我们要实现多继承的问题是在类中无法的到解决的,我们引出的接口就可以很好的帮助我们解决这个问题,在java中式可以实现多个接口的下面通过代码进行演示1.先创建一个父类(Animal)//创建一个动物类(Animal)classAnimal{protectedSt......
  • Java中的“抽象类“详解
    1.抽象类的定义在面向对象的概念中,所有的对象都是通过,类来描述的,但是反过来,不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个具体的对象,这样的类就是抽象类抽象类的概念是比较抽象的,比如现在有一个"父类"是"动物类",继承这个父类的子类中有"......
  • 中国开源网络安全软件Top 10 (2024版)
    在信息化快速发展的今天,网络安全问题愈加突出。中国的开源社区在网络安全领域贡献了许多优秀的开源软件,它们在实际应用中表现出色,广受好评。本文将介绍2024年最受欢迎的十款中国开源网络安全软件,并附上GitHub地址,供参考。雷池WAF社区版雷池WAF社区版是一款由长亭科技开发的Web......
  • 井底车场人员进入识别智慧矿山一体机行人不行车违章识别:安防网络摄像机的音频码流是如
    在安防监控领域,音频码流的计算对于优化存储和传输效率至关重要。本文将首先解释安防网络摄像机音频码流的计算方法,然后探讨这些原理如何应用于智慧矿山一体机,这款专为矿山安全监控设计的智能化设备。通过深入分析音频码流的计算和压缩技术,可以更好地理解智慧矿山一体机如何提升矿......
  • Java入门--运算符和表达式
    Java入门1、算术运算符实现对两个数的运算,程序输出效果为:请输入第一个整数:25请输入第二个整数:8两数相加的结果为:33两数相减的结果为:17两数相乘的结果为:200两数相除的结果为:3两数取余数的结果为:1以下是Java代码:publicclassCalculate{publicstaticvoidmain(......
  • 20222407 2024-2025-1 《网络与系统攻防技术》实验八实验报告
    1.学习内容1.Web前端:负责开发用户所看到的内容。前端语言:HTML、JavaScript(JS):与Java没有关系,与JSP两回事,CSS。Web前端框架:Vue.js(中国人尤雨溪)、Bootstrap(Twitter)、Layui(极简单)、Element-UI(基于Vue.js2.0,饿了么)、Angular(Google)……2.Web后端:主要使用各种库,API,Web服务等技术搭建......