5.13网络编程

只要在一个电脑中的两个进程之间可以通过网络进行通信那么拥有公网ip的两个计算机的通信是一样的。但是一个局域网中的两台电脑上的虚拟机是不能进行通信的,因为这两个虚拟机在电脑中又有各自的局域网所以通信很难实现。

socket套接字是一种用于网络间进行通信的方式,通过tcp与udp以及ip的方式与另外一个主机进行通信,为什么从传输层往下进行计算,因为应用层的方式协议非常的灵活,只要是有一个头和内容即可。但是在网络层数据链路层和传输层等不仅需要满足在两端的数据,还得要满足在硬件上的规定上。

Linux在主机端都是小端存储的,在网络端是大端进行存储的,记忆方式就是那个图这个是大端存储的方式。

所以说将在主机端的信息发布到网络上的时候需要先将信息将小端的方式转化为大端的方式。

【注意】区分大小端的时候是按字节进行划分的,字节内的数据是有序的。分为高字节和低字节,所以可以通过将数据打印为char类型数据判断(ASCII)

【注意】转换端口或者是ip进行大小端的转化需要使用不同的函数因为两者的长度不同。

htonl32位的(host与net)【转化ip】将ip主机字节序转化为网络字节序。

htons16位的【转化端口】将端口的主机字节序转化为网络字节序。

当然可以转过去也可以转回来,ntohl和ntohs函数

大小端的转换并不常用,因为我们常常使用char *字符串类型,所以使用下面的函数

一般在写的时候都是char *ip字符串类型,在进行传输的不便于使用192.如果是字符串类型仅这一小部分这个就是三个字节,所以将这个点分十进制转化为32位01数转化为int类型数字

int inet_aton(char *ip, struct in_addr*inp)将char*类型转化为大端方式转化为struct in_addr,与下面的函数有区别 

in_addr_t inet_addr(char *ip)将char*转化为in_addr_t类型(小端的方式)

char* inet_ntoa()将大端转化为char*

存储IP和端口定义的结构体struct sockaddr_in存储ipv4类型数据

【注意】但是一套接口接口可以适用于ipv4和ipv6的通信,所以bind等函数中使用这样一种struct sockaddr通用的一个类似的说明符实际上却没有这样的一个结构体定义,所以在实际应用的时候将sockaddr_in或者sockaddr_in6强转为sockaddr类型

【注意】sockaddr_in 是一个socket类,型的结构体存储ipv4 or 6,存储ip只是这个ipstruct in_addr类型存储用和端口号。struct in_addr 与 in_addr_t类型是一 一对应的,就是说在结构体中实际上存储的就是in_addr_t,所以说在使用的时候注意区分两者。

DNS dns将域名转化为ip

可以多个域名映射同一个ip,可以多个ip映射同一个域名(例如百度)。

gethostbyname给域名变ip,得到更多细节的函数是getaddrinfo函数可以通过一个域名得到所有的ip地址。

socket基于TCP进行通信的方式

socket设置一个socket文件对象(实际上是一个结构体)(理解为开辟一片区域,分配一个名字)

实际上是一个结构体,其中包含很多的内容,但是暂时只是关注两个缓冲区。

理解socket端点对象是开辟两个缓冲区:输入缓冲区和输入缓冲区。这个地方其实是和read和write系统调用函数类似将用户态的信息传递到内核态,然后将内核态中的信息传递到网卡上去然后传递到网络上,另一端同样从网卡上接收数据,读取到内核态中,然后传到用户态。

当listen之后就变成只负责接收的,最开始创建的这个socket节点只是负责接收信号进行排队。

【注意】这个地方的出入缓冲区是recv函数,是从网卡上接收数据!!!

bind就是设置服务器监听的端口,还有ip。理解这个地方是将自己的自己的ip和端口进行绑定,确定自己要监听的端口。(服务器端是固定端口号的,所以说在进行通信的时候,客户端需要知道服务器端的ip和端口号一般的端口号(http)都是固定的什么80,443)。

在自己进行端口的绑定的时候,不要使用系统定义的预留的端口1-1024,用8080及以上

为什么需要绑定ip,一般的电脑都是一个网卡,电脑有时也可能是有多个网卡,会有多个ip地址,所以绑定ip。当然也可以两个网卡都可以接收,想让两个网卡都接收就用0.0.0.0。

如果bind连接的时候,进行测试的时候,会用到ip127.0.0.1

【注意】在服务器端是自己设置一个端口,在客户端进行随机分配端口,因为客户端如果也是固定端口,这样的话不同的服务程序可能产生冲突,所以采用固定端口的方式。

这个指令查看端口有没有在使用

listen:监听端口

bind只是绑定,但是listen才开始监听

第二个参数,套接字挂起的最大端口号。全链接队列和半链接队列的长度之和。

调用listen函数会在服务器端维护两个缓冲区,是全链接队列和半链接队列。第一次握手完成就将socket节点放到半链接队列中,当完成三次握手的时候就放在全链接队列中。

全链接队列和半链接队列维护队列的数量的多少是在工作中不断确定的。

实际上客户机和服务器是没有什么本质区别的,所以说客户机也可以是服务器,同理。一般客户端不需要bind和listen。

【注意】当进行一次listen之后该socket节点就直接变成一个监听和接收队列,只进行监听和接收,后续当有新的connect的时候就不再需要connect了,就直接将相应的节点放到监听队列中。

connect进行了三次握手

只有当服务器端进行listen之后,客户端才能与服务器端建立链接。这个时候会报错,listen refused。

【注意】可以有多个客户端与整个服务器进行通信,都是通过socket一个节点接收信息

当完成三次握手以后,就已经建立了链接,(服务器端)socket节点就放到了全链接队列中。

accept在accept的时候是将原来的socket端点进行复制一个socket节点进行通信。(下文why)

借助于文件描述符找到节点的位置。

【注意】因为有多台客户机与服务器进行连接(1.最开始创建的socket节点只是负责三次握手,四次挥手都不负责),2.在基于TCP的连接中,给每一个客户端分配一个socket节点进行服务。这个时候客户端就会和服务器端新的socket节点进行通信而不会和原来的socket节点进行通信。

可以从accept进行三次握手以后,在新的socket节点中就可以获取客户端的ip和端口。也就是accept函数中后面的两个参数,因为ipv4和ipv6是不一样的,所以还需要传一个长度。一般就是用NULL,不需要显示打印出来的时候。当需要答应的时候注意将网络大端转化为主机小端模式。

accept是一个阻塞函数,当全链接队列为空的时候,服务端会阻塞在这个位置。

会返回新建立的socket节点的文件描述符。

recv和send进行通信

send就是将数据放到输出缓冲区中,recv就是从缓冲区中取出数据。传给网卡不关这个函数的关系。内核机制找到合适时间传到网卡,不关自己的操作,同样网卡也是找合适的时机被拿出数据

所以说这个地方可能会出现毡包,粘包的问题,因为放在缓冲区中的数据可能不会直接一次发送出去,或者不会立即发送和别的一块。

【注意】最近的函数中空标志不需要的位置一般都是用0

【注意】send和recv是放到网卡中

close关闭连接

【注意】TCP在客户端只需要close一次即可,服务器端需要close两次,一次接收的socket节点,一次进行通信socket节点

close之后可能不会立即进行四次挥手,(但是关闭以后进程一定关闭)close只是一次调用,由内核进行处理。同理ctrl+c可能不会由系统执行立即挥手。

select既可以随时进行监听和发送

【注意】两端都需要进行判断,如果说recv接收到的数据一直都往外爆出0,就有点像那个管道,所以说当读出的数据是0的时候就进行关闭。

close的时候可能还有一些数据没有进行发送,所以close函数会进行继续的发送。

close函数是自己发送FIN包请求与对方断开连接,等待对方的ACK和FIN断开连接

8081使用户端的端口处于time_wait状态,并不是8081是处于time_wait状态。

客户机和服务器那一端都可以先关闭,先关闭的一端是处于time_wait状态。

客户端的端口处于time_wait时,没有关系,因为客户端的端口是进行随机分配的

int reuse = 1;
setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

将这个语句加到服务器的socket函数和bind函数中间就可以。

断开重连(只是可以连上,但是不能接着进行)

会有应用场景,就是当客户端关掉断开连接服务器一直在工作,客户端再次上线的时候仍然可以工作。

就比如说一个音乐软件通过数据传输信息,暂停音乐以后再连接。

断开重连相比较于select函数就是分别取监听sockfd,STDIN_FILENO,

netstat命令 netstat -an 观察连接的状态,查看网络ip和端口的连接情况。

【注意】这个断开重连和聊天室程序都是会使用到两个fd_set监听集合(+memcpy函数),这样的话就不用每次进行添加监听文件描述符,

tcpdump  -w 保存抓包数据在工作中很重要,当客户端传不过来数据,或者是服务器端不能传输数据的时候,就是不正常的时候,也需要在Linux系统中也进行抓包,抓包得到的数据用wireshark打开这个文件抓包数据分析。

DDos修改客户端内核为一次连接,这样的话

UDP底层基于udp

UDP相较于TCP只有一个socket节点对象,如何判断将数据传送给谁,这个时候就需要在发送数据的时候带上要发送给那个客户机的socket节点ip和端口。

【注意】对比TCP和UDP,因为UDP是只有一个socket节点这样的话,需要服务器在第一次recvfrom的时候收到数据的时候将客户端的ip和端口保存下来。相比而言就需要一个额外的结构体socket结构体对象。

recvfrom的后面的两个参数是收取对方的socket节点套接字,以及长度和指针。发数据的时候指明要发送的socket对象。

需要客户端先发送数据给服务器,然后服务器才能知道客户端的ip和端口号

当一端的关闭的时候,另外一端是不知道的。

epoll进行IO多路复用(在一个线程中处理多个IO请求,因为是阻塞等待一个)

一般不会用elect函数(缺点很多),不会用poll(食之不好,弃之可惜),大多会用epoll函数。

监听和就绪分离(不需要重置监听集合),常驻内核态不需要来回的拷贝,没有1024个数限制,不像是select会进行不断地轮询检查而是

epoll是Linux系统内置的其他的系统有别的IO多路复用方式

监听对象是通过红黑树进行维护(也就是放到内核中),

在内核注册一种状态,类似一种回调机制。内核会检查这个列表,将就绪列表放到用户态,

select和epoll_wait有些像的,但是select是不断的上CPU轮询,但是epoll不是这样的,是等待。

epoll_create 创建epoll对象放在内核态,其中就会维护一个红黑树。

epoll_ctl()用于修改监听队列,可以添加可以删除队列中地对象,监听都还是写

其中最后一个参数就是epoll_event结构体机构体中typedef union epoll_data  union表示只能使用一次

epoll_wait用于查看就绪的队列(自己设置一个数组)数组的大小设置没有关系,先将小的fd返回,大的也不会丢失,之后再继续返回来再继续放到其中。只要是有一个就绪的就把它进行返回。

不需要每次都重置,返回成功的就绪个数

当需要跳出两层循环的时候,可以设置flag,当flag变化的时候,进行多次判断break。不要使用

goto不安全

框架:

通过网络通信(网络层和传输层的标准规范比较严格,考虑传输层和网络层socket定义)(应用层的传输规定相当的灵活不需要)--------------》

将主机上的数据传递到网络上去(注意数据存储的大小端的问题)--------》

基于传输层的两种不同的TCP和UDP分为两种逻辑

TCP:

客户端:   socket(得知服务器的ip和端口)----------------------------------------------------》

服务器端:socket(建立一个只是监听的socket节点)-----》bind(设置监听的端口和主机进行监听的ip)-------------》listen(设置全链接和半链接队列进行监听)

客户端:    connect(进行三次挥手)------------------------------>send和recv函数(将用户态数据到内核态)

服务器端:  accept(建立新的socket节点用于通信)-------------->send和recv函数(将用户态数据送到内核态)

UDP:

注意一些问题:

1. 在主机和网络上进行传输时注意大小端问题

2. 注意区分struct in_addr 与 in_addr_t其实一回事,struct中有in_addr_t

3. 注意在UDP设置新的sockaddr_in的时候记得要及时进行memset设置

4. 其实客户端和服务器输入的服务器的ip和端口都是服务器的,服务器在这个端口进行监听,客户端进行连接服务器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/838053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python接口自动化测试之动态数据处理

在前面的知识基础上介绍了在接口自动化测试中,如何把数据分离出来,并且找到它的共同点,然后依据这个共同点来找到解决复杂问题的思想。我一直认为,程序是人设计的,它得符合人性,那么自动化测试的&#xff0…

自由职业是种怎样的体验?普通人如何成为一名自由职业者?

自由职业在哪都能办公自由职业在哪都要办公。 放弃幻想,没有不辛苦的工作,5年经验后端开发程序员,已经从事自由职业1年半,今天就来客观分享一下自由职业的利与弊。 时间自由,减少中间商赚差价 自由职业最让人羡慕的就…

React Native 开发心得分享

有一段时间没更新了,花了点时间研究了下 React Native(后续用 RN 简称),同时也用该技术作为我的毕设项目(一个校园社交应用,仿小红书),经过了这段时间的疯狂折腾,对 RN 生态有了一定的了解&…

【实战selenium框架下在爱企查爬取企业的历史变更信息】文末附Google浏览器和驱动的下载

代码如下 # 导入包 import random import time from tkinter import filedialog import tkinter as tk import xlrd import os import datetime import csv from selenium import webdriver from selenium.webdriver import Keys from selenium.webdriver.common.by import By…

图搜索算法-最小生成树问题-普里姆算法(prim)

相关文章: 数据结构–图的概念 图搜索算法 - 深度优先搜索法(DFS) 图搜索算法 - 广度优先搜索法(BFS) 图搜索算法 - 拓扑排序 图搜索算法-最短路径算法-戴克斯特拉算法 图搜索算法-最短路径算法-贝尔曼-福特算法 图搜索…

Flutter 中的 AlertDialog 小部件:全面指南

Flutter 中的 AlertDialog 小部件:全面指南 在Flutter中,AlertDialog是一个用于显示警告、错误、信息或者确认消息的模态对话框。它提供了一种简单而直接的方式与用户进行交流,通常用于需要用户注意的重要信息或者需要用户做出决策的场合。本…

【069】基于SpringBoot+Vue实现的企业资产管理系统

系统介绍 基于SpringBootVue实现的企业资产管理系统管理员功能有个人中心,用户管理,资产分类管理,资产信息管理,资产借出管理,资产归还管理,资产维修管理。用户可以对资产进行借出和归还操作。因而具有一定…

计算机类的英语

Algorithm(算法)Binary code(二进制代码)Byte(字节)Cache(缓存)Database(数据库)Encryption(加密)Firewall(防火墙&#x…

软考-下午题-试题一

1、概念 2、答题技巧和规范 问题1、2:直接看 格式: 问题3: 格式: 3、例题 eg2:可以以后写完问题4之后,把问题3补充完整 问题4: 问题4 官方解释: 问题4(3‘) 2…

如何玩转github

如何玩转github 很多的小伙伴,经常会有这样的困惑,我看了很多技术的学习文档、书籍、甚至视频,我想动手实践,于是我打开了GitHub,想找个开源项目,进行学习,获取项目实战经验。这个时候很多小伙…

FDA认证的相关流程以及基本要求

一、FDA认证是什么? FDA认证,全称为"美国食品药品监督管理局认证"(U.S. Food and Drug Administration),是美国政府机构负责确保食品、药品、医疗器械和化妆品等产品的质量、安全和有效性。FDA认证是基于美…

在做题中学习(58):和为K的子数组

560. 和为 K 的子数组 - 力扣(LeetCode) 因为是判断子数组的和 要返回 k 的次数,所以 解法:前缀和 哈希表 提出一个概念:以下标i为结尾的所有子数组 那要找出所有和 k的子数组 就相当于:找出所有值为…

SD8002 集成电路芯片IC高电源输出功率1W功率音频放大器

对于SD8002A的表面级封装,日JA140℃/W,TJMAX150℃。依赖于系统工作的环境温度TA,(2)可 用于计算由芯片封装所能承受的内部最大功耗。如果式(1)的结果比式(2)大,此时就需要降低电 源电压或者提高负载阻值。在5V电源和8Ω负载的典型…

JAVA实验项目(二): 抽象类、接口的定义与使用

实验项目二 抽象类、接口的定义与使用 Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊&…

C#实现多线程的几种方式

前言 多线程是C#中一个重要的概念,多线程指的是在同一进程中同时运行多个线程的机制。多线程适用于需要提高系统并发性、吞吐量和响应速度的场景,可以充分利用多核处理器和系统资源,提高应用程序的性能和效率。 多线程常用场景 CPU 密集型任务…

Andrew Ng 吴恩达的深度学习课程作业 TensorFlow Tutorial (TF2兼容)

使用TensorFlow 2.6.0版本改写TensorFlow 1的代码,使用TF2兼容TF1的API。 1 - Exploring the Tensorflow Library 1.1 导入相关库 import math import h5py import matplotlib.pyplot as plt import numpy as np import tensorflow as tf from tensorflow.python…

物联网促进信息化——​青创智通工业物联网解决方案​

随着传感器网络(WSN)、无线射频识别(RFID)以及微电子机械系统(MEIVIS)等技术的不断成熟,扩展了人们对信息获取和使用的能力,并将提高制造效率、改善产品质量、降低产品成本和资源消耗、为用户提供更加透明和个性化的服…

玩转Matlab-Simscape(初级)- 05 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(理论部分1)

** 玩转Matlab-Simscape(初级)- 05 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(理论部分1) ** 目录 玩转Matlab-Simscape(初级)- 05 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&am…

AutoX.js入门教程

要使用AutoX.js创建一个自动化脚本,自动打开网易云音乐,搜索张学友的歌曲,并随机循环播放,然后将该脚本打包成APK文件,以下是实现这一过程的大致步骤: ### 步骤1:编写AutoX.js脚本 首先&#…

网关过滤器实现接口签名检验

背景 往往项目中的开放接口可能被别有用心者对其进行抓包然后对请求参数进行篡改,或者重复请求占用系统资源为此我们行业内使用比较多的策略是接口签名校验。签名校验的实现可以用注解aop的形式实现,也可以使用过滤器统一拦截校验实现,此篇文…