网络编程原理二

简介: 网络编程原理二

TCP / IP 协议



应用层

传输层

互联网层

数据链路层

物理层


image.png


一、应用层



应用层是我们网络编程主要针对的地方,也是程序员进行主要交互的一层。我们来看一些应用协议有哪些,以及应用层协议的两种形式。


1. 常用的现有应用层协议


DNS(域名系统)

HTTP(超文本传送协议)

FTP(文件传输协议)

Telnet(远程终端协议)


2. 自定义协议


开发之前,建立约定。开发过程中就会让客户端和服务器之间严格遵守协议约定好的格式。

自定义协议大体分成两类:


(1) 文本格式


文本格式即把请求响应当成字符串来处理,处理的基本单位是字符。

常见的文本格式有两类:xml,json

因为文本格式较为简单,当然自己也可以约定文本格式。


① xml

xml 是一种格式化组织数据的方式,它在 Java 标准库中有其对应的实现,这种格式不仅可以用于自定义协议,也可以用于网络传输。

格式如下:

整个 xml 是由 " 标签 " 构成的,此外,标签是成对出现的。


比方说: <num1> 10 </num1>
开始标签: <num1>  
结束标签: </num1>
中间值:   10
请求:               响应:
<request>             <response>
  <num1> 10 </num1>         <result> 30 </result>
  <num2> 20 </num2>       </response>
  <operator> + </operator>
</request>


② json


json 是一种键值对的方式,同样地,它在 Java 标准库中有其对应的实现。


格式如下:

键和值之间使用 [冒号] 分割,键值对之间使用 [逗号] 分割。


请求:               响应:
{                 {
  num1: 10,             result: 30
  num2: 20,           }
  operator: "+"
}


2) 二进制格式


把请求响应当成二进制数据处理,处理的基本单位是字节

protobuffer,thift…


3. 理解自定义协议


我们先来看一下以 【文本 + 分隔符】的方式,来自己设计一个协议。


UdpCalServer 用来描述服务器
UdpCalClient  用来描述客户端


(1) 基于 UDP 的 socket 写一个计算器运算


① UdpCalServer


package demo1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpCalServer {
    private DatagramSocket socket = null;
    public UdpCalServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动!");
        while (true) {
            //2. 读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            //3. 根据请求构造响应
            String response = process(request);
            //4. 构造响应并返回
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                    response.getBytes().length, requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //顺便打印日志
            String log = String.format("[%s : %d], req: %s; resp: %s",
                    requestPacket.getAddress().toString(), requestPacket.getPort(),
                    request, response);
            System.out.println(log);
        }
    }
    private String process(String request) {
        String[] strings = request.split(";");
        if (strings.length != 3) {
            System.out.println("你所输入的格式不正确!");
            return null;
        }
        int num1 = Integer.parseInt(strings[0]);
        int num2 = Integer.parseInt(strings[1]);
        String key = strings[2];
        int result = 0;
        if (key.equals("+")){
            result = num1 + num2;
        } else if (key.equals("-")) {
            result = num1 - num2;
        } else if (key.equals("*")) {
            result = num1 * num2;
        } else {
            result = num1 / num2;
        }
        return result + "";
    }
    public static void main(String[] args) throws IOException {
        UdpCalServer server = new UdpCalServer(9090);
        server.start();
    }
}


② UdpCalClient


package demo1;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class UdpCalClient {
    private String serverIp;
    private int serverPort;
    private DatagramSocket socket = null;
    public UdpCalClient(String serverIp, int serverPort) throws SocketException {
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        this.socket = new DatagramSocket();
    }
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入格式:num1; num2; +-*/ ");
        while (true) {
            System.out.println("输入计算的数和符号 ->");
            String request = scanner.nextLine();
            if (request.equals("exit")) {
                System.out.println("Exit!");
                return;
            }
            //1. 构造请求并发送
            DatagramPacket requestPacket = new DatagramPacket(
                    request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIp), serverPort );
            socket.send(requestPacket);
            //2. 尝试获取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
            //3,显示响应结果
            String log = String.format("req: %s  resp: %s", request, response);
            System.out.println(log);
            System.out.println();
        }
    }
    public static void main(String[] args) throws IOException {
        UdpCalClient client = new UdpCalClient("127.0.0.1", 9090);
        client.start();
    }
}


通信结果:


a4e5e7d85c3a4b2ba46249500727d8e7.png


在上面的例子中,我们可以看到:当计算 15+3 = 18 这个逻辑的时候,我们在服务器与客户端通信之前,就两边约定好了,将操作数放在前两位,操作符放在后一位,它们之间通过 ; 来分割。也就说,格式为:【15;3;+】

所以说,自定义协议本质上也是一种提前的约定。


这个和我们开头说的例子是一样的:网友A 和 网友B 见面,他们提前就要告知对方今天穿什么颜色的上衣和裤子,否则就算到达同一地点,也很难找到找到彼此。


4. DNS


DNS:Domain Name System ( 域名系统 )


什么是域名?


类似于

www.baidu.com www.sogou.com


可以看到,域名就是通过一串单词通过点来进行分割的,在我们传统的叫法,域名实际上就是某某网站…


在传输数据的时候,先根据域名,再转换成对应的 IP地址,最后根据 IP地址进行传输。因为,IP地址是通过点分十进制来表示的,对于日常使用的网络用户来说,相对不好理解,而使用域名,就相当于为 IP地址 套上了一层外套,域名也就更加形象了。


二、传输层



传输层只负责端对端的数据传输,即只考虑起点和终点,不考虑中间过程。

传输层是操作系统内核实现的,因此谈到的传输层协议,一般都是指现成的一些协议,很少会涉及 " 自定制 "。


TCP / UDP 协议就是传输层中的主要协议。


1. 深入理解端口号


之前的博客提到:端口号其实是用来标识一个进程的。


一个主机中的所有进程都是通过同一个网卡来传输数据的,让每个进程分别绑定到不同的端口号,此时收到的网络数据报中就会包含一个 " 目的端口 ",它就会根据目的端口找到对应端口号的进程,从而把数据交给对应的进程。


2. 端口号和 PID 的区别


在学习线程的时候,我们了解过 PID 的概念,PID( Process Identification ),即进程标识符,操作系统里每打开一个程序都会创建一个进程 ID,即 PID. 但我们必须明确:程序在运行的时候,PID 是不会改变标识符的,但进程终止后,PID 标识符就会被系统回收,就可能会被继续分配给新运行的程序,所以说 PID 是临时的一个标志。


但是,端口号是固定不变的。


所以说:在网络编程中,我们指定一个程序 / 进程 与服务器通信,需要知道 主机的 IP地址 和 进程的端口号。而不能用 PID 来代替端口号!


举个例子:你打中国移动 10086,准备办理流量套餐,那么对面就会有人工客服接听电话,当你办理好了套餐之后,就把电话挂了。但你发现,电话套餐忘记办理了,于是就再次打电话过去,这个时候,你会发现,系统为你分配的客服和上一个客服就不再是同一个人了。那么,端口号就相当于 10086 这个固定的号码,而不同的客服就表示不同的 PID。


3. 注意


(1)


通常情况下,一个进程对应一个端口号,两个进程无法绑定同一个端口。


而比较常见的情况是:一个进程能够对应多个端口。这是通过 socket 文件和端口绑定来实现的,因为一个进程可以有多个文件,那么就可以做到让多个 socket 文件绑定到不同的端口。


让一个进程对应多个端口,实际上是为了解决【调试问题】,通常情况下,服务器会提供客户端一个【业务端口】,这个端口为客户端提供服务,如果在提供服务的时候,出现了数据问题怎么办?这时候,就可以事先让当前进程再绑定另一个【调试端口】,而这个端口就是用来定位一些问题。


(2)


端口号是一个两个字节整数,那么最多也就是 16 位,所以它的范围为 0- 65535.


知名端口号: 0 - 1023
注册端口号: 1024 - 49151
剩下的端口号叫动态端口号或私有端口号: 49152 - 65535


目录
相关文章
|
30天前
|
机器学习/深度学习 PyTorch TensorFlow
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic,深度学习探索者。深耕TensorFlow与PyTorch,分享框架对比、性能优化与实战经验,助力技术进阶。
|
1月前
|
监控 负载均衡 安全
WebSocket网络编程深度实践:从协议原理到生产级应用
蒋星熠Jaxonic,技术宇宙中的星际旅人,以代码为舟、算法为帆,探索实时通信的无限可能。本文深入解析WebSocket协议原理、工程实践与架构设计,涵盖握手机制、心跳保活、集群部署、安全防护等核心内容,结合代码示例与架构图,助你构建稳定高效的实时应用,在二进制星河中谱写极客诗篇。
WebSocket网络编程深度实践:从协议原理到生产级应用
|
7月前
|
机器学习/深度学习 存储 算法
NoProp:无需反向传播,基于去噪原理的非全局梯度传播神经网络训练,可大幅降低内存消耗
反向传播算法虽是深度学习基石,但面临内存消耗大和并行扩展受限的问题。近期,牛津大学等机构提出NoProp方法,通过扩散模型概念,将训练重塑为分层去噪任务,无需全局前向或反向传播。NoProp包含三种变体(DT、CT、FM),具备低内存占用与高效训练优势,在CIFAR-10等数据集上达到与传统方法相当的性能。其层间解耦特性支持分布式并行训练,为无梯度深度学习提供了新方向。
241 1
NoProp:无需反向传播,基于去噪原理的非全局梯度传播神经网络训练,可大幅降低内存消耗
|
2月前
|
机器学习/深度学习 人工智能 算法
卷积神经网络深度解析:从基础原理到实战应用的完整指南
蒋星熠Jaxonic带你深入卷积神经网络(CNN)核心技术,从生物启发到数学原理,详解ResNet、注意力机制与模型优化,探索视觉智能的演进之路。
308 11
|
2月前
|
机器学习/深度学习 算法 搜索推荐
从零开始构建图注意力网络:GAT算法原理与数值实现详解
本文详细解析了图注意力网络(GAT)的算法原理和实现过程。GAT通过引入注意力机制解决了图卷积网络(GCN)中所有邻居节点贡献相等的局限性,让模型能够自动学习不同邻居的重要性权重。
269 0
从零开始构建图注意力网络:GAT算法原理与数值实现详解
|
2月前
|
安全 测试技术 虚拟化
VMware-三种网络模式原理
本文介绍了虚拟机三种常见网络模式(桥接模式、NAT模式、仅主机模式)的工作原理与适用场景。桥接模式让虚拟机如同独立设备接入局域网;NAT模式共享主机IP,适合大多数WiFi环境;仅主机模式则构建封闭的内部网络,适用于测试环境。内容简明易懂,便于理解不同模式的优缺点与应用场景。
307 0
|
4月前
|
机器学习/深度学习 人工智能 PyTorch
零基础入门CNN:聚AI卷积神经网络核心原理与工业级实战指南
卷积神经网络(CNN)通过局部感知和权值共享两大特性,成为计算机视觉的核心技术。本文详解CNN的卷积操作、架构设计、超参数调优及感受野计算,结合代码示例展示其在图像分类、目标检测等领域的应用价值。
215 7
|
6月前
|
监控 应用服务中间件 Linux
掌握并发模型:深度揭露网络IO复用并发模型的原理。
总结,网络 I/O 复用并发模型通过实现非阻塞 I/O、引入 I/O 复用技术如 select、poll 和 epoll,以及采用 Reactor 模式等技巧,为多任务并发提供了有效的解决方案。这样的模型有效提高了系统资源利用率,以及保证了并发任务的高效执行。在现实中,这种模型在许多网络应用程序和分布式系统中都取得了很好的应用成果。
159 35
|
6月前
|
机器学习/深度学习 算法 测试技术
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析
本文探讨了基于图的重排序方法在信息检索领域的应用与前景。传统两阶段检索架构中,初始检索速度快但结果可能含噪声,重排序阶段通过强大语言模型提升精度,但仍面临复杂需求挑战
158 0
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析
|
5月前
|
安全 Java 程序员
分析Muduo网络库源码中的TcpServer组件工作原理
简言之,TcpServer 在 Muduo 中的角色,就是一位终极交通指挥员,它利用现代计算机网络的魔法,确保数据如同车辆一般,在信息高速公路上自由、安全、高效地流动。
64 0
下一篇
开通oss服务