网络编程(TCP协议,UDP协议)

目录

网络编程三要素

IP

IPv4

InetAddress类

端口号

协议

UDP协议

UDP协议发送数据

UDP协议接收数据

UDP的三种通信方式(代码实现)

TCP协议

TCP通信程序

三次握手和四次挥手

练习

1、客户端:多次发送数据服务器:接收多次接收数据,并打印

2、客户端:发送一条数据,接收服务端反馈的消息并打印

服务器:接收数据并打印,再给客户端反馈消息

3、客户端:将本地文件上传到服务器。接收服务器的反馈。服务器:接收客户端上传的文件,上传完毕之后给出反馈。


什么是网络编程?

在网络通信协议下,不同计算机上运行的程序,进行的数据传输。

常见软件架构有哪些?

CS/BS

通信的软件架构CS\BS的各有什么区别和优缺点

CS:客户端服务端模式需要开发客户端

BS:浏览器服务端模式不需要开发客户端,

CS:适合定制专业化的办公类软件如:IDEA、网游

BS:适合移动互联网应用,可以在任何地方随时访问的系统


C/S(Client/Server)架构是一种分布式计算模型,其中客户端和服务器分别承担不同的功能和责任。客户端是面向用户的界面和应用程序,负责向用户提供交互界面和功能。服务器则负责处理客户端发送的请求,进行数据处理和存储,并将处理结果返回给客户端。

B/S(Browser/Server)架构也是一种分布式计算模型,类似于c/s架构。不同之处在于,b/s架构中的客户端是基于浏览器的Web应用程序,通过浏览器访问Web服务器上的应用程序。服务器处理客户端请求,并将结果通过Web页面返回给客户端。

总体而言,c/s架构适用于需要实现复杂业务逻辑和功能的应用程序,而b/s架构适用于面向广大用户的Web应用程序。

网络编程三要素

IP:设备在网络中的地址,是唯一的标识。

端口号:应用程序在设备中唯一的标识。

协议:数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。

IP

全称:Internet Protocol,是互联网协议地址,也称IP地址。

是分配给上网设备的数字标签。

常见的IP分类为:IPv4、IPv6

IPv4

全称:Internet Protocol version4,互联网通信协议第四版

采用32位地址长度,分成4组

网际协议版本4(IPv4)是互联网通信中应用最广泛的网络协议之一,它负责将数据包从源头发送到目的地。IPv4使用32位地址格式,能够提供约43亿个独立的地址。这些地址被用于在互联网上唯一标识每个网络设备,如计算机、手机或其他终端设备。

IPv4的核心功能包括无连接的数据传输和最大努力交付。无连接意味着在数据传输之前,不需要建立持久的连接状态。每个数据包都是独立处理并路由至目标地址。最大努力交付则表明该协议尽力将数据包传送到目的地,但不保证所有数据包均能成功到达,也不保证它们会按顺序到达。这些特性需要由更高层的协议,如传输控制协议(TCP),来加以管理和修正。

IPv4的设计和结构对其普及和功能至关重要。IPv4数据包包含一个固定长度的头部,通常为20字节,后面可跟随可选的扩展部分。固定头部包括多个字段,如版本号、首部长度、总长度、标识、标志、片偏移、生存时间(TTL)、协议、首部校验和、源地址和目的地址等。这些字段共同确保了数据包的正确传输及其优先级、路由和错误校验。

由于IPv4地址的枯竭问题,互联网社区早在1990年代就开始研究替代方案。最终,网际协议版本6(IPv6)被开发出来,以解决地址空间不足的问题。IPv6使用128位地址格式,可以提供近乎无限的地址空间。尽管IPv6在技术上解决了IPv4的许多限制,但由于技术升级和迁移的复杂性,IPv6的普及速度相对较慢。

总结来说,IPv4作为互联网的基础协议,虽然存在一些限制,但它在过去几十年里成功地支撑了互联网的迅猛发展。然而,随着IPv4地址的耗尽和互联网需求的不断增长,向IPv6的过渡已成为不可逆转的趋势。未来,IPv6可能会完全取代IPv4,成为互联网通信的主流协议。

InetAddress类

static InetAddress getByName(string host) 确定主机名称的IP地址,主机名称可以是机器名称,也可以是IP地址

String getHostName() 获取此IP地址的主机名

String getHostAddress() 返回文本显示中的IP地址字符串

java 复制代码
package InetAddress24_6_21;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo1 {
    public static void main(String[] args) throws UnknownHostException {
        //1.获取InetAddress的对象
        // IP的对象 一台电脑的对象
        InetAddress address=InetAddress.getByName("努力敲代码的小火龙");
        System.out.println(address);

        String name = address.getHostName();
        System.out.println(name);

        String ip = address.getHostAddress();
        System.out.println(ip);
    }
}

端口号

应用程序在设备中唯一的标识。

端口号:由两个字节表示的整数,取值范围:0~65535

其中0~1023之间的端口号用于一些知名的网络服务或者应用。

我们自己使用1024以上的端口号就可以了。

注意:一个端口号只能被一个应用程序使用,

协议

计算机网络中,连接和通信的规则被称为网络通信协议

OSI参考模型和TCP/IP参考模型是网络通信中常用的两种参考模型,用于描述计算机网络中不同层次的协议和功能。两种参考模型的各层对应的协议如下:

OSI参考模型的七层对应协议:

  1. 物理层:主要负责传输比特流,按照电气、光学或者机械方式传送信号。没有具体的协议对应。

  2. 数据链路层:主要负责将比特流分成具有特定意义的帧,并进行错误检测和纠正。常用的协议有以太网(Ethernet)和无线局域网(Wi-Fi)。

  3. 网络层:主要负责将数据包从源主机传输到目标主机,包括寻址、路由选择和包分片等功能。常用的协议有Internet协议(IP)。

  4. 传输层:主要负责提供端到端的可靠数据传输,包括流量控制和拥塞控制等功能。常用的协议有传输控制协议(TCP)和用户数据报协议(UDP)。

  5. 会话层:主要负责建立、管理和终止应用程序之间的通信会话。没有具体的协议对应。

  6. 表示层:主要负责处理数据的表示和转换,确保不同主机上的应用程序能够解释和理解数据的意义。没有具体的协议对应。

  7. 应用层:最上层的应用程序直接面向用户,并提供特定的网络服务,例如电子邮件(SMTP)、文件传输(FTP)和域名系统(DNS)等。

TCP/IP参考模型的四层对应协议:

  1. 网络接口层(网络接入层):主要负责将数据链路层的帧封装为IP数据包,并进行物理传输。常用的协议有以太网(Ethernet)和无线局域网(Wi-Fi)。

  2. 网际层(互联网层):主要负责将数据包从源主机传输到目标主机,包括寻址、路由选择和包分片等功能。常用的协议有Internet协议(IP)。

  3. 传输层:主要负责提供端到端的可靠数据传输,包括流量控制和拥塞控制等功能。常用的协议有传输控制协议(TCP)和用户数据报协议(UDP)。

  4. 应用层:最上层的应用程序直接面向用户,并提供特定的网络服务,例如电子邮件(SMTP)、文件传输(FTP)和域名系统(DNS)等。

需要注意的是,TCP/IP参考模型的网络接口层对应了OSI参考模型的物理层和数据链路层。因此,TCP/IP参考模型只有四层,而OSI参考模型有七层。

UDP协议

用户数据报协议(User Datagram Protocol)

UDP是面向无连接通信协议。

速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据

UDP协议发送数据

java 复制代码
package UDPDemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        //发送数据
        //创建Datagramsocket对象
        //绑定端口,以后我们就是通过这个端口往外发送
        // 空参:所有可用的端口中随机一个进行使用
        // 有参:指定端口号进行绑定
        DatagramSocket ds=new DatagramSocket();
        //打包数据
        String str="hello world";
        byte[] bytes=str.getBytes();
        InetAddress address=InetAddress.getByName("127.0.0.1");
        int port=10086;
        //数据打包
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length,address,port);

        //发送数据
        ds.send(dp);

        //释放资源
        ds.close();
    }
}

UDP协议接收数据

java 复制代码
package UDPDemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ReceiveMessageDemo {
    public static void main(String[] args) throws IOException {
        //1.创建Datagramsocket对象(快递公司)
        //在接收的时候,一定要绑定端口
        //而且绑定的端口一定要跟发送的端口保持一致
        DatagramSocket ds=new DatagramSocket(10086);
        //接收数据包
        byte[] bytes=new byte[1024];
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
        //该方法是阻塞的,程序执行到这一步的时候,会在这里死等,等发送端发送消息
        ds.receive(dp);

        //解析数据包
        byte[] data=dp.getData();
        int len=dp.getLength();
        InetAddress address=dp.getAddress();
        int port=dp.getPort();

        System.out.println("接收到数据"+new String(data,0,len));
        System.out.println("这个数据是从"+address+"这台电脑中的"+port+"这个端口发出的");

        //释放资源
        ds.close();
    }
}

先运行接收端,再运行发送端

UDP的三种通信方式(代码实现)

单播

  • 之前的代码就是单播

组播

  • 组播地址:224.0.0.0~239.255.255.255
  • 其中224.0.0.0~224.0.0.255 为预留的组播地址

三个接收端:

java 复制代码
package UDPDemo2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class ReceiveMessageDemo3 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms=new MulticastSocket(10000);
        //将当前本机,添加到224.0.0.1的这一组当中
        InetAddress address=InetAddress.getByName("224.0.0.1");
        ms.joinGroup(address);
        //接收数据包
        byte[] bytes=new byte[1024];
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
        ms.receive(dp);

        //解析数据包
        byte[] data=dp.getData();
        int len=dp.getLength();
        int port=dp.getPort();

        System.out.println("这个数据是从"+address+"这台电脑中的"+port+"这个端口发出的,发出的数据为"+new String(data,0,len));

        //释放资源
        ms.close();
    }
}

发送端

java 复制代码
package UDPDemo2;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        
        MulticastSocket ms=new MulticastSocket();
        //打包数据
        String str="hello world";
        byte[] bytes=str.getBytes();
        InetAddress address=InetAddress.getByName("224.0.0.1");
        int port=10000;
        //数据打包
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length,address,port);

        //发送数据
        ms.send(dp);

        //释放资源
        ms.close();
    }
}

广播

  • 广播地址:255.255.255.255
java 复制代码
package UDPDemo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendMessageDemo {
    public static void main(String[] args) throws IOException {
        //发送数据
        //创建Datagramsocket对象
        //绑定端口,以后我们就是通过这个端口往外发送
        // 空参:所有可用的端口中随机一个进行使用
        // 有参:指定端口号进行绑定
        DatagramSocket ds=new DatagramSocket();
        //打包数据
        String str="hello world";
        byte[] bytes=str.getBytes();
        InetAddress address=InetAddress.getByName("255.255.255.255");
        int port=10086;
        //数据打包
        DatagramPacket dp=new DatagramPacket(bytes,bytes.length,address,port);

        //发送数据
        ds.send(dp);

        //释放资源
        ds.close();
    }
}

TCP协议

传输控制协议TCP(Transmission Control Protocol)

TCP协议是面向连接的通信协议。

速度慢,没有大小限制,数据安全。

TCP通信程序

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象通信之前要保证连接已经建立

通过Socket产生I0流来进行网络通信

客户端

  • 创建客户端的Socket对象(Socket)与指定服务端连接 Socket(string host,int port)
  • 获取输出流,写数据 Outputstream getoutputstream()
  • 释放资源
java 复制代码
package TCPDemo;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //创建Socket对象
        // 在创建对象的同时会连接服务端,如果连接不上,代码会报错
        Socket socket=new Socket("127.0.0.1",10001);

        //可以从连接通道中获取输出流
        OutputStream os=socket.getOutputStream();
        //写出数据
        os.write("你好你好".getBytes());
        //释放资源
        os.close();
        socket.close();
    }
}

服务器

  • 创建服务器端的Socket对象(ServerSocket) ServerSocket(int port)
  • 监听客户端连接,返回一个Socket对象 Socket accept()
  • 获取输入流,读数据,并把数据显示在控制台 InputStream getInputstream()
  • 释放资源 void close()
java 复制代码
package TCPDemo;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //创建对象ServerSocker
        ServerSocket ss=new ServerSocket(10001);
        //监听客户端的链接
        Socket socket=ss.accept();
        //从连接通道中获取输入流读取数据
        InputStream is=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        int b;
        while ((b=isr.read())!=-1){
            System.out.println((char)b);
        }
        //释放资源
        socket.close();
        ss.close();
    }
}

三次握手和四次挥手

三次握手(Three-way Handshake)和四次挥手(Four-way Fin-Wait-RST)是TCP协议中建立和终止连接的过程。

1. 三次握手

三次握手是指在TCP连接建立过程中,客户端和服务器端需要进行三次报文交换,以确保双方的发送和接收能力都正常。具体过程如下:

a) 客户端向服务器端发送一个带有SYN标志的报文,表示请求建立连接。

b) 服务器端收到客户端的SYN报文后,会回复一个带有SYN和ACK标志的报文,表示同意建立连接。

c) 客户端收到服务器端的SYN+ACK报文后,会回复一个带有ACK标志的报文,表示连接已建立。

2. 四次挥手

四次挥手是指在TCP连接终止过程中,客户端和服务器端需要进行四次报文交换,以确保双方的数据都已经被对方接收并处理完毕。具体过程如下:

a) 客户端向服务器端发送一个带有FIN标志的报文,表示请求终止连接。

b) 服务器端收到客户端的FIN报文后,会回复一个带有ACK标志的报文,表示已经收到了客户端的终止请求。

c) 服务器端在处理完所有数据后,向客户端发送一个带有FIN标志的报文,表示同意终止连接。

d) 客户端收到服务器端的FIN报文后,会回复一个带有ACK标志的报文,表示连接已终止。

练习

1、客户端:多次发送数据

服务器:接收多次接收数据,并打印

客户端

java 复制代码
package Test1;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket=new Socket("127.0.0.1",10001);

        Scanner sc=new Scanner(System.in);
        OutputStream os=socket.getOutputStream();

        while (true){
            System.out.println("请输入数据");
            String str=sc.nextLine();
            //退出方法
            if("886".equals(str)){
                break;
            }
            //写出数据
            os.write(str.getBytes());
        }

        //释放资源
    }
}

服务器

java 复制代码
package Test1;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(10001);
        //等待客户端来连接
        Socket socket = ss.accept();
        //读取数据
        InputStream is=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        int b;
        while ((b=isr.read())!=-1){
            System.out.print((char) b);
        }
        //释放资源
        socket.close();
        ss.close();
    }
}

2、客户端:发送一条数据,接收服务端反馈的消息并打印

服务器:接收数据并打印,再给客户端反馈消息

客户端

java 复制代码
package Test2;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;


public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket=new Socket("127.0.0.1",10001);

        //写出数据
        String str="你好呀";
        OutputStream os = socket.getOutputStream();
        os.write(str.getBytes());

        //写出结束标记
        socket.shutdownOutput();

        //接收服务端的回写数据
        InputStream is=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        int b;
        while ((b=isr.read())!=-1){
            System.out.print((char) b);
        }

        //释放资源
        socket.close();
    }
}

服务端

java 复制代码
package Test2;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(10001);
        //等待客户端链接
        Socket socket = ss.accept();
        //从socket中获取输入流读取数据
        InputStream is = socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        int b;
        while ((b=isr.read())!=-1){
            System.out.print((char)b);
        }

        //回写数据
        String str="hello";
        OutputStream os = socket.getOutputStream();
        os.write(str.getBytes());

        //释放资源
        socket.close();
        ss.close();
    }
}

3、客户端:将本地文件上传到服务器。接收服务器的反馈。

服务器:接收客户端上传的文件,上传完毕之后给出反馈。

客户端

java 复制代码
package Test3;

import java.io.*;
import java.net.Socket;


public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket=new Socket("127.0.0.1",10001);
        //读取本地文件中的数据,并写到服务器当中
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\java\\net\\clientdir\\a.jpg"));
        BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
       byte[] bytes=new byte[1024];
       int len;
       while ((len=bis.read(bytes))!=-1){
           bos.write(bytes,0,len);

       }
        bos.flush();
       //往服务器写出的结束标记
        socket.shutdownOutput();
       //接收服务器的回写数据
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = br.readLine();
        System.out.println(line);

        //释放资源
        socket.close();
    }
}

服务端

java 复制代码
package Test3;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(10001);
        //等待客户端链接
        Socket socket = ss.accept();
        //读取数据并保存到本地文件中

        BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("E:\\java\\net\\serverdir\\a.jpg"));

        int len;
        byte[] bytes=new byte[1024];
        while ((len=bis.read())!=-1){
            bos.write(bytes,0,len);
        }
        bos.flush();
        //回写数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("上传成功");
        bw.newLine();
        bw.flush();
        //释放资源
        socket.close();
        ss.close();
    }
}

这一期就到这里啦

努力遇见更好的自己!!!

相关推荐
兮动人2 小时前
Eureka注册中心通用写法和配置
java·云原生·eureka
爱编程的小白L4 小时前
基于springboot志愿服务管理系统设计与实现(附源码)
java·spring boot·后端
聪明的笨猪猪6 小时前
Java Redis “持久化”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
聪明的笨猪猪6 小时前
Java Redis “核心基础”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
奋斗的小monkey8 小时前
Spring Boot 3.x核心特性与性能优化实战
java·spring boot·微服务·性能优化·响应式编程
程序猿DD9 小时前
将 GPU 级性能带到企业级 Java:CUDA 集成实用指南
java·架构
一成码农9 小时前
JavaSE面向对象(上)
java
qq_574656259 小时前
java-代码随想录第66天|Floyd 算法、A * 算法精讲 (A star算法)
java·算法·leetcode·图论
我是好小孩9 小时前
【Android】六大设计原则
android·java·运维·服务器·设计模式