基础网络编程

Posted Al_tair

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基础网络编程相关的知识,希望对你有一定的参考价值。

网络编程

大家好呀!我是小笙!本节我和大家分享一下网络编程的基础知识!

网络编程

网络基础知识

概念

  • 概念:两台或者多台设备之间通过网络实现数据传输
  • Java.net包下提供了一系列的类和接口用来实现网络通信
  • 网络的覆盖范围
    • 局域网:一个机房或者教室
    • 城域网:一个城市
    • 广域网:全国甚至全球范围

IP地址

  • 概念:用来标识每一台电脑主机 <=> 地址
  • 查看ip地址:ipconfig
  • 组成:网络地址+主机地址 如 192.168.16.22

IPv6的地址长度为128位,16个字节是IPv4的四倍

域名

概念:将ip地址映射成域名

目的:解决记忆ip地址困难的问题

www.baidu.com <=> 180.101.49.11

端口号

概念:用于标识特定的网络服务程序(注意是网络服务需要端口,普通程序并不一定需要占用端口)

范围:以整数形式 0~65535(2个字节) (注意0~1024通常被占用

网络通讯协议

数据,在网络编程中,数据的组织形式就是协议(需要按照规定好的协议方式)

TCP 和 UDP

InetAddress

实现功能

方法:(InetAddress对象: 主机名/IP地址)

  • 获取本机的InetAddress对象 — localHost
  • 根据指定主机名获取InetAddress对象 — InetAddress.getByName(“主机名”)
  • 根据域名返回InetAddress对象 — InetAddress.getByName(“域名”)
  • 通过InetAddress对象,获取对应的IP地址 — InetAddress对象.getHostAddress()
  • 通过InetAddress对象 获取对应的主机名或者域名 — InetAddress对象.getByName(“主机名”)

操作代码示例

需要捕获异常,可能会出现异常

比如找不到local host 或者不允许找

// 需要捕获异常,可能会出现异常
try 
    // 1.获取本机的InetAddress对象  --- LAPTOP-EINLAL7G/192.168.56.1
    InetAddress InetObject1 = InetAddress.getLocalHost();
    System.out.println("InetObject1: "+ InetObject1);

    // 2.根据指定主机名获取InetAddress对象  --- LAPTOP-EINLAL7G/192.168.56.1
    InetAddress InetObject2 = InetAddress.getByName("LAPTOP-EINLAL7G");
    System.out.println("InetObject2: "+ InetObject2);

    // 3.根据域名返回InetAddress对象  --- www.taobao.com/60.163.129.165
    InetAddress InetObject3 = InetAddress.getByName("www.taobao.com");
    System.out.println("InetObject3: "+ InetObject3);

    // 4.通过InetAddress对象,获取对应的IP地址  --- 180.101.49.11
    InetAddress InetObject = InetAddress.getByName("www.baidu.com");
    System.out.println(InetObject.getHostAddress());

    // 5.通过InetAddress对象 获取对应的主机名或者域名 --- www.jd.com/60.165.115.3
    InetObject = InetAddress.getByName("www.baidu.com");
    System.out.println(InetObject.getByName("www.jd.com"));

catch(Exception e)

Socket

编程方式:1.TCP编程 可靠 2.UDP编程 不可靠

TCP网络通信编程

客户端 <==> 服务端

发送一次数据案例(字节流)

题目要求如下

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接服务端并发送一串字符串(字节数组) 然后退出
  4. 服务端接收到客户端发送的信息 输出并退出

实现代码

客户端

public class ClientTCP 
    /**
     * 客户端
     * 思路:
     * 1.连接服务端(ip,端口)
  
     */
    public static void main(String[] args) throws IOException 
        //  1.连接服务端(ip,端口)
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        // 2.连接上服务端,生成socket 并通过socket.getOutputStream()写入数据
        OutputStream outputStream = socket.getOutputStream();
        // 输入想要传输的字符串进行传输
        System.out.println("请你输入想要传输的字符串");
        String str = new Scanner(System.in).next();
        byte[] out = str.getBytes();
        outputStream.write(out) ;
        System.out.println("传输成功!!");

        // 3.最后要释放流 and socket
        outputStream.close();
        socket.close();
        System.out.println("客户端结束传输");
    

服务端

public class TCPServer 
    /**
     * 服务端
     * 思路:
     * 1.设置监听端口为9999
     * 2.监听客户端,是否有建立连接
     *   如果建立连接则通过socket.getInputStream()接受数据
     *   如果没有建立连接则一直等待直到建立连接
     * 3.最后要释放流 and socket serverSocket
     */
    public static void main(String[] args) throws IOException 
        // 1.设置监听端口为9999
        ServerSocket serverSocket = new ServerSocket(9999);

        // 2.监听客户端,是否有建立连接
        // 如果没有建立连接则一直等待直到建立连接
        System.out.println("开始接收数据....");
        Socket socket = serverSocket.accept();

        // 如果建立连接则通过socket.getInputStream()接受数据
        // 如果没有传入数据则等待数据的传入
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readLength = 0;
        while((readLength = inputStream.read(buf)) != -1)
            System.out.println("接收到数据:"+new String(buf,0,readLength));
        

        // 3.最后要释放流 and socket serverSocket
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务端结束传输");
    

实现结果

数据往返传输案例 (字节流)

题目要求如下

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接服务端并发送一串字符串(字节数组)并且接收到服务端传来的数据并且显示 然后退出
  4. 服务端接受到客户端发送的信息并传送回一串字符串(字节数组) 然后退出

注意点:socket传输完需要添加结束标记 如:socket.shutdownInput(); // 关闭输入流 socket.shutdownOutput(); // 关闭输出流

客户端

public class ClientTCP 
    /**
     * 客户端
     * 思路:
     * 1.连接服务端(ip,端口)
     * 2.连接上服务端,生成socket 并通过socket.getOutputStream()写入数据
     * 3.接收服务器传来的数据并显示
     * 4.最后要释放流 and socket
     */
    public static void main(String[] args) throws IOException 
        //  1.连接服务端(ip,端口)
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);

        // 2.连接上服务端,生成socket 并通过socket.getOutputStream()写入数据
        OutputStream outputStream = socket.getOutputStream();
        // 输入想要传输的字符串进行传输
        System.out.println("请你输入想要传输的字符串");
        String str = new Scanner(System.in).next();
        byte[] out = str.getBytes();
        outputStream.write(out) ; 
        System.out.println("传输成功!!");
        socket.shutdownOutput();  // 关闭输出流

        // 3.接收服务器传来的数据并显示
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readLength = 0;
        while((readLength = inputStream.read(buf)) != -1)
            System.out.println("接收到数据:"+new String(buf,0,readLength));
        

        // 4.最后要释放流 and socket
        inputStream.close();
        outputStream.close();
        socket.close();
        System.out.println("客户端结束传输");
    

服务端

public class TCPServer 
    /**
     * 服务端
     * 思路:
     * 1.设置监听端口为9999
     * 2.监听客户端,是否有建立连接
     *   如果建立连接则通过socket.getInputStream()接受数据
     *   如果没有建立连接则一直等待直到建立连接
     * 3.接受到数据并且传送回一串字符串
     * 4.最后要释放 流 and socket and serverSocket
     */
    public static void main(String[] args) throws IOException 
        // 1.设置监听端口为9999
        ServerSocket serverSocket = new ServerSocket(9999);

        // 2.监听客户端,是否有建立连接
        // 如果没有建立连接则一直等待直到建立连接
        System.out.println("开始接收数据....");
        Socket socket = serverSocket.accept();

        // 如果建立连接则通过socket.getInputStream()接受数据
        // 如果没有传入数据则等待数据的传入
        InputStream inputStream = socket.getInputStream();
        byte[] buf = new byte[1024];
        int readLength = 0;
        while((readLength = inputStream.read(buf)) != -1)
            System.out.println("接收到数据:"+new String(buf,0,readLength));
        
        socket.shutdownInput(); // 关闭输入流

        // 3.接受到数据并且传送回一串字符串
        System.out.println("想要输出撒?");
        OutputStream outputStream = socket.getOutputStream();
        String str = new Scanner(System.in).next();
        outputStream.write(str.getBytes());
        System.out.println("输出成功!!!");


        // 4.最后要释放流 and socket serverSocket
        outputStream.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务端结束传输");
    

实现结果

数据往返传输案例 (字符流)

题目要求如下

  1. 编写一个服务端和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接服务端并发送一串字符串并且接收到服务端传来的数据并且显示 然后退出
  4. 服务端接受到客户端发送的信息并传送回一串字符串 然后退出

演示核心代码

// 客户端
String str = new Scanner(System.in).next();
//  转换流重点:An OutputStreamWriter is a bridge from character streams to byte streams
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(str) ;
bufferedWriter.newLine(); // 换行符 表示写入的内容结束  注意对方必须是使用readline()
bufferedWriter.flush();  // 如果使用的是字符流,需要手动去刷新,否则数据将无法写入数据通道 
System.out.println("传输成功!!");

// 服务端
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
System.out.println(bufferedReader.readLine());

// 注意关闭外层流
bufferedWriter.close();
bufferedReader.close();
发送一张图片

题目要求如下

  1. 编写一个服务端和一个客户端
  2. 服务端在8899端口监听
  3. 客户端连接到服务端,发送一张图片 地址:C:\\Users\\Ushop\\Desktop\\mess\\Java\\Al_tair.png
  4. 服务端接受到客户端发送的图片,保存到src下,然后再发送“收到图片”再退出
  5. 客户端接受到“收到图片”再退出

我遇到了一点小问题,暂时还不清楚原因:只能传输.jpg图片,不能传输.png图片

代码如下

客户端

public class TCPFileuploadClient 
    /**
     * 客户端
     * 1. 编写一个服务端和一个客户端
     * 2. 服务端在8899端口监听
     * 3. 客户端连接到服务端,发送一张图片 地址:C:\\Users\\Ushop\\Desktop\\mess\\Java\\Al_tair.png
     * 4. 服务端接受到客户端发送的图片,保存到src下,然后再发送“收到图片”再退出
     * 5. 客户端接受到“收到图片”再退出
     */
    public static void main(String[] args) throws Exception 
        // 1. 连接到服务端8899端口
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);

        // 2.创建读取磁盘文件放入输入流
        String filePath = "C:\\\\Users\\\\Ushop\\\\Desktop\\\\JavaLoad\\\\JavaSe\\\\Image\\\\pandas.jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));

        // 3.通过socket获取到输入流,将byte数据发送到服务端
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);
        socket.shutdownOutput(); // 结束输出流

        // 4.接受服务端发来的“收到图片”

        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(reader.readLine());

        // 5.关闭相关资源
        reader.close();
        bis.close(); 
        bos.close();
        socket.close();
    

服务端

public class TCPFileuploadServer 
    /**
     * 服务端
     * 1. 编写一个服务端和一个客户端
     * 2. 服务端在8899端口监听
     * 3. 客户端连接到服务端,发送一张图片 地址:C:\\Users\\Ushop\\Desktop\\mess\\Java\\Al_tair.png
     * 4. 服务端接受到客户端发送的图片,保存到src下,然后再发送“收到图片”再退出
     * 5. 客户端接受到“收到图片” 再退出
     */
    public static void main(String[] args) throws Exception 
        // 1.服务端在本地监听8899端口
        ServerSocket serverSocket = new ServerSocket(9999);

        // 2.服务端等待连接
        System.out.println("等待客户端发送数据.....");
        Socket socket = serverSocket.accept();

        // 3.读取客户端发送的数据 通过Socket得待输入流
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);

        // 4.将得到的byte数组,写入到指定的路径,就得到一个文件了
        String descFilePath = "E:\\\\Java_training\\\\Java_code\\\\JavaIdea03\\\\java\\\\Javase_HSping\\\\src\\\\com\\\\Al_tair\\\\socket\\\\upload\\\\pandas.jpg";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFilePath));
        bos.write(bytes);


        // 5.向客户端发送“收到图片”
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.write("收到图片");
        writer.newLine();
        writer.flush();

        // 6.最后关闭其他资源
        bis.close();
        bos.close();
        writer.close();
        socket.close();
        serverSocket.close();

    

工具类 :将.转换成byte[]字节数组

public class StreamUtils 
    /**
     * 功能:将输入流转换成byte[]字节数组
     */
    public static byte[] streamToByteArray(InputStream inputstream) throws Exception
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 创建输出流对象
        byte[] b = new byte[1024]; // 字节数组
        int len;
        while((len = inputstream.read(b))!= -1)
            byteArrayOutputStream.write(b,0,len);
        
        byte[] array = byteArrayOutputStream.toByteArray(); // 将输出流转换成字节数组
        byteArrayOutputStream.close();
        return array;
    

netstat 指令(补充)

  1. netstat -an 可以查看当前主机网络情况,包括端口监听和网络连接情况

  2. netstat -an | more 可以分页显示 ctrl+c退出该指令

  3. dos控制行以管理员身份打开 netstat -anb 可以查看哪个应用软件监听该端口

  4. 当客户端连接到服务端后实际上客户 TCP/IP随机分配的端口(验证:netstat观测)

UDP网络通信编程[了解]

基本介绍

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

UDP网络通信编程案例

任务要求:

  1. 编写一个接受端A和一个发送端B
  2. 接受端A 在9999端口等待接收数据报
  3. 发送端B向接收端A发送数据“hello~”
  4. 接收端A接收到发送端B发送的数据回复“hello , Im fine”,再退出
  5. 发送端B接收到回复的数据再退出

但是注意程序启动顺序还是有区别的,接收方要先启动程序!!!

public class udpNodeB 
    /**
     * Node B
     * 1. 编写一个接受端A和一个发送端B
     * 2. 接受端A 在9999端口等待接收数据报
     * 3. 发送端A向接收端B发送数据“hello~”
     * 4. 接收端B接收到发送端A发送的数据回复“hello , Im fine”,再退出
     * 5. 发送端A接收到回复的数据再退出
     */
    public static void main(String[] args) throws IOException 
        // 1.创建一个DatagramSocket对象,准备在9998端口接收数据
        DatagramSocket socket = new DatagramSocket(9998);

        // 2.将需要发送的数据封装到 DatagramPacket对象 (UDP协议 数据包MAX 64K)
        System.out.println("开始聊天界面...");
        String str = new Scanner(System.in).next();
        byte[] data = str.getBytes();

        // 3.封装的 DatagramPacket对象组成: data 数据 | data.length 数据长度 | 主机(IP) | 端口(port)
        // send 方法发送数据
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.56.1"), 9999);
        socket.send(packet);
        System.out.println("数据发送成功!!");
        
        // 复制接受端A的j数据的方式
        byte[] buf = new byte[64*1024];
        packet = new DatagramPacket(buf,buf.length);
        socket.receive(packet);
        String s = new 计网网络层首部

计网网络层首部

网际协议版本4(IPv4)

谢烟客---------Linux之网络基础知识

网络基础tcp/ip协议四

简述 HTTP 缓存首部及其行为