网络编程(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();
    }
}

这一期就到这里啦

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

相关推荐
对许3 分钟前
Java操作Excel最佳实践
java·spark·excel
高级程序源10 分钟前
springboot学生档案信息管理系统-计算机毕业设计源码96509
java·spring boot·spring·eclipse·mybatis·idea
martian66533 分钟前
学懂C#编程:属性(Property)的概念定义及使用详解
java·开发语言·c#·属性·property
阿亮说技术44 分钟前
Java毕业设计 基于SSM vue电影院票务系统小程序 微信小程序
java·微信小程序·毕业设计·课程设计
时间瑾1 小时前
线程池实践篇
java·开发语言
ffyyhh9955111 小时前
记一次kafka使用不当导致的服务器异常
java
不要飞升1 小时前
百日筑基第十一天-看看SpringBoot
java·spring boot·后端·实习
萝卜地里的兔子1 小时前
面向对象编程思想新解 第二章 编程的本质
java·开发语言
xw-pp1 小时前
回溯法的小结与概述
java·数据结构·c++·python·算法·递归
创作小达人1 小时前
InnoDB中的表级锁、页级锁、行级锁详解
java·数据库·mysql