网络编程day6

一、模拟面试

C语言中指针数组和数组指针的区别        指针数组本质上是一个数组,该数组中元素是指针变量,故指针数组是用来存储指针变量的一个数组;
        数组指针本质上是一个指针变量,是存储数组地址的指针变量,该变量记录了数组的起始地址,该指针变量的偏移量为数组的数据类型大小。
结构体的字节对齐

        结构体的字节对齐需要遵循结构体成员对齐和整体对齐原则;
        成员之间的对齐原则按照自身的类型字节大小整数倍对齐,即成员变量的存储起始位置必须是自身类型大小的整数倍;        

        整体对其原则是按照最大字节成员数组类型的字节大小和8字节取小值,作为整体的对齐原则,为其分配对应的空间。

TCP和UDP的区别

        TCP和UDP都是用于传输层的两种传输协议;

        TCP是面向连接的稳定的传输,进行传输前需要进行连接,停止发送也会进行断连,UDP是面向无连接的快速的传输,在传输时可以不用连接;

        TCP的传输不是实时的,等待合适时机以数据包的形式传输数据,因此可能会出现数据粘包的现象,UDP的传输是实时的,有多少传输多少,超出数据包大小的数据直接丢弃。

        TCP发送数据包时,接收会向发送端返回ACK确认包,发送包收到相应数据包对应的ACK应答包,才会向接收端发送下一个数据包,同样,接收端再没有接受到下一个数据包之前,也会一直发送当前接收到的数据包的ACK应答包,因此TCP具有很高的稳定,确定性,不会出现数据丢失,重复的现象,而UDP不会这样,发送端只会在最短的时间内将数据发送给接收端,接收端会对接收到的数据进行校验。
        因此TCP的效率低,稳定性高,数据传输正确性高,一般用于重要数据的传输,如账号密码等;UDP传输效率高,稳定性差,一般用于对实时性要求高的传输,如共享屏幕,视频通话等。

同步通信和异步通信的区别

        同步通信是指阻塞的通信,异步通信是指非阻塞的通信;

        同步通信指的是在多个任务通信时需要按照规定的逻辑顺序去进行,以避免对临界资源的错误访问和处理;同步通信信息连续发送,形成一个数据帧,当一个通信任务进行资源访问时其它通信任务阻塞等待;
        异步通信则不会出现阻塞等待,例如消息队列,多任务可以非阻塞的异步的使用消息队列进行通信。

谈谈对多线程的理解

        线程是任务调度的最小单位,多线程指的是在一个进程中有多个进程并发执行;

        线程的五个基本状态分别为创建,就绪,运行,阻塞和死亡态,多线程就是并发执行多个任务,一个线程被创建且被唤醒后才进入就绪状态,等待CPU进行调度,当任务进行I/O申请等阻塞操作时会被挂起进入阻塞态,阻塞结束后才进入就绪态,运行中的任务在时间片用完后也会再次进入就绪队列等待CPU分配时间片,任务完成后进入死亡态;
        线程消耗的资源小,但是多个线程共享同一个进程的资源,因此一个线程出现问题可能会对其它线程造成影响,进程则一般不会;

        线程在用户空间和内核空间进行切换时消耗的资源更少,因此多线程适合I/O密集型操作。

大小端和大小端的验证

        因不同主机架构不同,在对多字节整数进行存储时,会出现大小端的问题,数据高位存储在地址低位的存储方式称为大端存储,数据低位存储在地址低位的存储方式称为小端存储;
        大小端验证一般采取指针或者共用体的方法进行验证,用指针变量指向存储多字节整数变量的地址,然后将指针强转为单字符指针类型的指针变量,打印强转后指针变量指向地址的数据便可以判断出大小端存储;共用体发原理相似,共用体共享同一片内存空间,在共用体中定义一个多字节整数变量和一个单字符变量,初始化共用体中的多字节整数变量后,打印单字符变量,以此来判断大小端存储。

        大小端的转换多用与跨主机的通信,因为不同主机可能存在大小端异同,所以在跨主机的网络通信中,主机在对多字节整数进行处理时需要先转换成网络字节序再在网络中进行传输,在接收到网络中的多字节整数时需要先将其转换成主机字节序才能使用,网络字节序为大端存储。

什么是互斥锁        在多个任务对同一个临界资源进行访问时会出现资源争夺的竞态,造成错误,因此,引入互斥锁机制;
        互斥锁本质上也是一个临界资源,当我们现需要对一个临界资源进行异步处理时可以定义一个互斥锁变量,当多个任务对同一临界资源进行争夺时,需要先争夺互斥锁资源,当申请到互斥锁资源后才可以对对应的临界资源进行访问,在结束使用临界资源时释放互斥锁资源;
共享内存的特点

        共享内存是System V提供的一种用于多进程通信的机制,其原理是在在内存中为进程映射一块物理内存,映射到此块物理内存的进程可以通过这块内存进行数据的交互;

        共享内存具有高效率,避免了进程间通信时数据拷贝的开销

        共享内存中的数据具有持久性,直到该块内存的数据被刷新;
        多进程使用共享内存时也可能会出现竞态,因此通常使用同步机制如信号灯集来同步进程间的通信。

描述一下C语言中的指针

        我们通常说的C语言指针指的是指针变量,指针指的是地址,指针变量是存储地址的变量,指针不可以变化,而指针变量可以变化;
        指针变量有两个属性,一个是它存储的地址值,一个是它指向的数据类型,指针变量指向一块内存地址时,其偏移量为该指针定义时的给的数据类型;

        指针的声明格式为type *var_name,其中type表示指针指向的数据类型,var_name是指针变量的名称。例如,int *ptr; 声明了一个指向整数类型的指针ptr

        指针的值即为一个内存地址,通常通过取地址运算符&来获取变量的地址并赋给指针。例如,int a = 10; int *pa = &a; 将整型变量a的地址存储在指针pa中;

        使用解引用操作符*可以通过指针访问或修改其所指向地址的值。例如,执行*pa = 100; 可以将pa指向地址的值修改为100。

        指针可以进行加减运算,这类运算是依据其所指向数据类型的大小进行的。例如,int *ptr; ptr+1;会使ptr的地址值增加sizeof(int)的字节数;

        空指针和void指针。空指针用于表示一个指针不指向任何有效内存地址,而void指针是一种通用指针类型,可指向任何类型的数据;
        数组名本质上就是一个指针常量,可以使用数组名对数组成员进行访问;

        指针可以作为函数参数传递,使得函数能够修改传入的实际参数。同时,函数也可以返回指针类型的数据。
        

gcc分布编译

预处理  gcc -E     test.c  -o  test.i

编译      gcc -S     test.i   -o   test.s

汇编      gcc -c      test.s  -o  test.o 

链接        gcc      test.o  -o  test  生成 可执行文件test 

 预处理:展开头文件,替换宏定义,删除注释;

 编译:检查语法问题,出现错误会报错,编译停止,没有错误会生成汇编文件;

 汇编:生成一个不可执行的二进制文件;

 链接:链接库函数将不可执行二进制文件生成可执行二进制文件。

说一下对套接字的理解

        使用socket函数可以创建一个套接字文件,该函数返回一个文件描述符作为操作该文件的句柄,该文件里维护了两个缓冲区,一个数据的接受区,一个数据的发送区,可以实现全双工通信;

        套接字文件多用于跨主机的网络通信中,例如在TCP和UDP中都使用了套接字;

        套接字的的类型分为流式域套接字(TCP使用),数据报(UDP),和原套接字(允许直接访问底层协议(如IP或ICMP),用于特殊应用场景,比如网络协议的开发和底层网络操作);
        接套字由IP地址、端口号和协议类型三部分组成;

        套接字的通信流程:
                                        ①创建套接字

                                        ②绑定操作

                                        ③建立连接

                                        ④数据传输

        对于TCP,服务器端需要创建同于连接的套接字后开启监听,再监听到客户端的connect请求后使用accept创建用于通信的套接字,对于UDP,服务器端和客户端都只需要创建一个用于通信的套接字即可;TCP和UDP通信中,服务器端都必须要进行绑定,客户端没有强制要求。

HTTP        和TCP、UDP的关系

        HTTP(超文本传输协议)是应用层的协议,一般使用TCP(传输控制协议)完成,TCP和UDP(用户数据报协议)是传输层的协议;

        HTTP是一种应用层协议,主要用于在Web浏览器和服务器之间传输网页和其他资源。它规定了客户端如何向服务器发送请求,以及服务器如何响应这些请求。由于HTTP需要可靠传输,确保数据完整无误地到达对方,因此它通常建立在TCP协议之上。TCP提供面向连接、可靠传输的服务,通过三次握手建立连接,四次挥手关闭连接,确保数据传输的可靠性和顺序性;
        UDP则是一种无连接的传输层协议,它不保证数据的可靠性和顺序性,但在某些应用场景下,如实时音视频传输、DNS查询等,对实时性要求高、能够容忍部分数据丢失的情况,UDP更适用。由于UDP的这些特性,HTTP一般不会直接使用UDP进行数据传输。不过,随着技术发展,有些特定情况下可能会研究基于TCP和UDP混合的HTTP协议,以优化特定场景下的传输性能。

如何使用IP地址和子网掩码得到你需要的网络的网段IP地址 & 子网掩码 得到需要的网络的网段
计算机网络中的OSI七层模型和TCP/IP的四层结构

        OSI七层模型是一个详细的网络通信协议分层标准,由国际标准化组织(ISO)制定。它包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层;

        TCP/IP四层结构是基于实际应用而发展起来的模型,包括应用层、传输层、网络层和网络接口层。与OSI模型相比,TCP/IP模型更为简洁,将表示层、会话层和部分传输层的功能融合到了应用层,把数据链路层和物理层合并为网络接口层。该模型广泛应用于互联网,成为事实上的国际标准。

数据结构中栈和队列的区别

        栈和队列都是操作受限的线性表;

        栈只允许对队列的一端进行操作,包括入栈和出栈操作,

队列只允许再两端进行不同的操作,一端入队,一端出队;

        栈对数据的操作是先进后出(FILO),队列对数据的操作是先FIFO);对于栈,插入操作称为压栈(push),删除操作称为弹栈(pop),都只对栈顶进行操作;而对于队列,插入操作称为入队(enqueue),删除操作称为出队(dequeue),分别在队尾和队首进行操作。

        栈的大小通常在创建时就已经确定,无法动态调整;而队列可以通过添加新的节点来扩展其大小。

顺序表和链表的区别

        顺序表是顺序存储的线性表,链表是链式存储的线性表,顺序表在逻辑和物理上都是连续的,链表在逻辑上联系,物理上不一定连续;

        顺序表在物理存储上连续,可以直接访问任意元素,时间复杂度为O(1),链表在物理存储上不一定连续,所以在访问任意元素时需要从头开始遍历,时间复杂度为O(n);

        顺序表元素的插入和删除需要移动大量元素来保持其连续性,时间复杂度为O(n),而链表的插入和删除只需要改变相邻元素的指针,时间复杂度为O(1)(在已知待操作节点位置的情况下);

        顺序表在使用前就已经分配了最大的空间,实际使用的空间小于分配的空间,所以会造成空间的浪费,链表的空间是动态分配的,所以不存在空间浪费的情况;

        顺序表的大小在创建时就已经确定,无法动态调整;而链表可以通过添加新的节点来扩展其大小。

TCP/IP的三次握手和四次挥手

三次握手:

        ①:客户端向服务器端发送SYN连接请求包;

        ②:服务器端收到客户端发来的SYN请求包后向客户端回复对应的ACK应答包,并向其发送同意连接的SYN请求包;

        ③:客户端收到服务器端发来的SYN请求包后,向服务器端发送对应的ACK应答包,至此,二者建立连接。

四次挥手:

        ①发起方向被发起方发送FIN断开连接请求包;

        ②被发起方向发起方回复对应的ACK应答包,表示接收到了断开请求,此时如果被发起方还有数据传输需求可以继续发送数据给发起方;

        ③被发起方向发起方发送FIN断开连接请求包;

        ④发起方接收到被发起方的FIN请求包,回复对应的ACK应答包,至此,二者解除连接。

                    

TCP/IP为什么是三次握手
  1. 确认双方的接收和发送能力:通过三次握手,双方都可以确认对方的发送和接收能力是否正常。如果一方无法正常接收或发送数据,那么在握手过程中就会检测到这个问题,从而避免了后续数据传输出现问题。

  2. 避免网络延迟引起的问题:三次握手过程中,双方都需要等待对方的响应。这样可以确保双方都有足够的时间来处理请求和响应,避免了因网络延迟而导致的问题。

  3. 确保数据的完整性:三次握手过程中,双方都可以确认对方发送的数据是否正确。如果发现数据有误,那么可以在握手阶段就终止连接,避免了错误的数据传输。

  4. 同步序列号:三次握手过程中,双方都会发送一个序列号给对方。这样可以让双方都知道接下来要发送的第一个数据包的序列号,从而实现数据的有序传输。

指针和指针变量
  1. 指针是一个数据类型,它存储了另一个变量、数组或者函数等的内存地址。指针本身只包含一个地址,并没有实际存储数据的功能。

  2. 指针变量则是一个实际的变量,它的值是一个指针。这意味着指针变量存储了一个地址,这个地址指向内存中的某个位置,而在这个内存位置上,我们可以存储或读取数据。

共享内存和消息队列的优缺点

共享内存的优点:

  1. 高效性:共享内存允许多个进程直接访问同一块内存区域,避免了数据拷贝的开销,因此具有较高的传输效率。
  2. 实时性:由于没有中间环节,共享内存可以实现实时通信,适用于需要快速响应的场景。
  3. 易于管理:共享内存的数据结构可以在一个进程中创建和维护,其他进程可以直接访问,便于管理和调试。

共享内存的缺点:

  1. 同步问题:多个进程同时访问共享内存可能导致数据不一致的问题,需要使用同步机制(如互斥锁、信号量等)来保证数据的一致性。
  2. 安全性:共享内存可能会受到恶意软件的攻击,需要采取安全措施来保护共享内存区域。
  3. 不易扩展:当进程数量增加时,共享内存的管理和维护会变得复杂,难以适应大规模的系统。

消息队列的优点:

  1. 解耦性:消息队列将发送者和接收者分离,使得它们之间的通信更加灵活,可以在不同的时间、不同的地点进行通信。
  2. 可扩展性:消息队列可以支持多个生产者和消费者,具有良好的扩展性,适用于大规模系统的通信需求。
  3. 容错性:消息队列通常具有持久化功能,即使发送方或接收方崩溃,消息仍然可以在恢复后继续传递。

消息队列的缺点:

  1. 延迟:消息队列需要进行消息的存储和检索,可能会导致一定的延迟。
  2. 顺序性:在某些情况下,消息队列可能无法保证消息的顺序性,需要额外的处理来确保顺序。
  3. 资源消耗:消息队列需要额外的存储空间来保存消息,可能会占用较多的系统资源。
结构体中一个char 一个int结构体占字节长度是多少8字节

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值