亿联视频面试

\1. tcp和udp的区别?

​ TCP编程的服务器端一般步骤是:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt(); * 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();

4、开启监听,用函数listen();

5、接收客户端上来的连接,用函数accept();

6、收发数据,用函数send()和recv(),或者read()和write();

7、关闭网络连接;

8、关闭监听;

TCP编程的客户端一般步骤是:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt();* 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选

4、设置要连接的对方的IP地址和端口等属性;

5、连接服务器,用函数connect();

6、收发数据,用函数send()和recv(),或者read()和write();

7、关闭网络连接;

与之对应的UDP编程步骤要简单许多,分别如下:

UDP编程的服务器端一般步骤是:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt();* 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();

4、循环接收数据,用函数recvfrom();

5、关闭网络连接;

UDP编程的客户端一般步骤是:

1、创建一个socket,用函数socket();

2、设置socket属性,用函数setsockopt();* 可选

3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选

4、设置对方的IP地址和端口等属性;

5、发送数据,用函数sendto();

6、关闭网络连接;

\2. 什么是字节流?什么是数据报?

字节流是由字节组成的 。 一个连续的字节队列

tcp是基于字节流的,没有边界,udp是数据报,每个包之间有边界。

数据报是通过网络传输的数据的基本单元,包含一个报头(header)和数据本身,其中报头描述了数据的目的地以及和其它数据之间的关系。数据报是完备的、独立的数据实体,该实体携带要从源计算机传递到目的计算机的信息,该信息不依赖以前在源计算机和目的计算机以及传输网络间交换。

两者的区别在于TCP接收的是一堆数据,而每次取多少由主机决定;而UDP发的是数据报,客户发送多少就接收多少。

拥有这些区别的原因是由于TCP和UDP的特性不同而决定的。TCP是面向连接的,也就是说,在连接持续的过程中,socket中收到的数据都是由同一台主机发出的,因此,知道保证数据是有序的到达就行了,至于每次读取多少数据自己看着办。 而UDP是无连接的协议,也就是说,只要知道接收端的IP和端口,且网络是可达的,任何主机都可以向接收端发送数据。这时候,如果一次能读取超过一个报文的数据,则会乱套。比如,主机A向发送了报文P1,主机B发送了报文P2,如果能够读取超过一个报文的数据,那么就会将P1和P2的数据合并在了一起,这样的数据是没有意义的。

\3. tcp为什么可靠?

TCP为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。 此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在才会发送数据,从而可以控制通信流量的浪费。

1、序列号与确认号

当发送错误的时候,会发生:

a、超时重传机制

b、快速重传机制

2、流量控制(滑动窗口)

滑动窗口的流量控制可以包括那么几个协议:

a、停等协议。

b、后退n步协议。

c、选择重传。

3、拥塞控值

下面说明下几个符号说明:

cwnd:拥塞窗口大小

ssthreshold: 拥塞阈值 (该阈值是对网络状况的一个预估,决定在拥塞窗口多大的时候采取怎样的策略,它的初始化一般是一个估计,一般都会给出)

现在可以看下这个拥塞控制机制包括哪几个策略

a、慢启动

此时一般是(记住是一般情况)cwnd<ssthreshold,此时cwnd呈指数形式增长,1、2、4、8、16、32…这种增长趋势

b、拥塞避免

此时一般cwnd>ssthreshold,此时cwnd呈线性增长,32、33、34、35…这种增长趋势

c、拥塞解决

此时一般是遇到了网络拥塞的状况,解决方法是拥塞阈值乘性减即ssthreshold=cwnd/2,cwnd=1,或者ssthreshold=cwnd/2,cwnd=ssthreshold,这两种情况在后面说明

d、快速恢复

一般是启用拥塞结局策略之后,根据不同的情况,进入慢启动或者拥塞避免阶段。

\4. 指针和引用的区别?

1.指针和引用的定义和性质区别:

(1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来

的变量实质上是同一个东西,只不过是原变量的一个别名而已。如:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。

而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单

元。

(2)引用不可以为空,当被创建的时候,必须初始化,而指针可以是空值,可以在任何时候被初始化。

(3)可以有const指针,但是没有const引用;

(4)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)

(5)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;

(6)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。

(7)”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小;

(8)指针和引用的自增(++)运算意义不一样;

(9)如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏;

\5. c语言和c++的区别?

\6. 面向对象的三大特征?介绍一下?

面向对象的三大特征是抽象、继承、多态。

面向对象是一种软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、人工智能等领域。

面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

抽象是指强调实体的本质、内在的属性。在系统开发中,抽象指的是在决定如何实现对象之前的对象的意义和行为。使用抽象可以尽可能避免过早考虑一些细节。

1、封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

2、继承性。

继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。

3、多态性

多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。

\7. 父类的析构函数为什么是虚函数?

将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用父类指针指向该子类对象,释放父类指针时可以释放掉子类的空间,防止内存泄漏。

C++默认的***析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存***。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。

C++中析构函数的作用

析构函数与构造函数对应,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。

析构函数名也应与类名相同,只是在函数名前面加一个位取反符,例如stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。

如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。

如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。

类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。

静态函数和虚函数的区别:

静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销

请你说一说你理解的虚函数和多态

多态的实现主要分为静态多态和动态多态,***静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。***举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了virtual关键字的函数,在子类中重写时候不需要加virtual也是虚函数。

虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

\8. vector和list的区别?

1.vector数据结构

vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。

因此能高效的进行随机存取,时间复杂度为o(1);

但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。

另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。

2.list数据结构

list是由双向链表实现的,因此内存空间是不连续的。

只能通过指针访问数据,所以list的随机存取非常没有效率,时间复杂度为o(n);

但由于链表的特点,能高效地进行插入和删除。

2、区别:

1)vector底层实现是数组;list是双向 链表。

2)vector支持随机访问,list不支持。

3)vector是顺序内存,list不是。

4)vector在中间节点进行插入删除会导致内存拷贝,list不会。

5)vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。

6)vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。

\9. 五层网络模型?

物理层:主要作用是定义物理设备如何传输数据(光缆,网线)

数据链路层:为通讯实体间建立数据链路连接

网络层:为数据在节点之间传输创建逻辑链路

传输层:数据的传输都是在这层定义的,数据过大分包,分片。

应用层:为应用软件提供了很多服务,构建于协议之上。

OSI七层模型

OSI中的层 功能 TCP/IP协议族

应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet

表示层 数据格式化,代码转换,数据加密 没有协议

会话层 解除或建立与别的接点的联系 没有协议

传输层 提供端对端的接口 TCP,UDP

网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP

数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU

物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2

\10. 项目中是怎么使用tcp来进行控制传输的?

三次握手

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。

确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。

确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效

同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。

终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接

PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。

字段 含义

URG 紧急指针是否有效。为1,表示某一位需要被优先处理

ACK 确认号是否有效,一般置为1。

PSH 提示接收端应用程序立即从TCP缓冲区把数据读走。

RST 对方要求重新建立连接,复位。

SYN 请求建立连接,并在其序列号的字段进行序列号的初始值设定。建立连接,设置为1

FIN 希望断开连接。

四次挥手

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

\1. struct和class的区别

​ C++中的 struct 和 class 基本是通用的

答:(一)默认继承权限。如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;
(二)成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。

class还可用于定义模板参数,像typename,但是关键字struct不能同于定义模板参数

C++保留struct关键字,原因

· 保证与C语言的向下兼容性,C++必须提供一个struct

· C++中的struct定义必须百分百地保证与C语言中的struct的向下兼容性,把C++中的最基本的对象单元规定为class而不是struct,就是为了避免各种兼容性要求的限制

· 对struct定义的扩展使C语言的代码能够更容易的被移植到C++中

private 与public 即是私有的与公有的。 也就是说:private 定义的属性或者方法只本身能够访问。 public 是拥有该对象实例就可以访问。

\2. c和c++的联系

C++ 是在C语言的基础上增加新特性

从语法上看,C语言是C++的一部分,C语言代码几乎不用修改就能够以 C++ 的方式编译

早期并没有“C++”这个名字,而是叫做“带类的C”。“带类的C”是作为C语言的一个扩展和补充出现的,它增加了很多新的语法,目的是提高开发效率

1C++支持面向过程编程、面向对象编程(OOP)和泛型编程,而C语言仅支持面向过程编程。

2C++是C的超集,它兼容大部分的C的语法的结构。

C和C++的区别

1C是面向过程的语言,而C++是面向对象的编程语言(面向对象的思想)

​ 面向对象的程序设计语言必须有描述对象及其相互之间关系的语言成分。这些程序设计语言可以归纳为以下几类:系统中一切事物皆为对象;对象是属性及其操作的封装体;对象可按其性质划分为类,对象成为类的实例;实例关系和继承关系是对象之间的静态关系;消息传递是对象之间动态联系的唯一形式,也是计算的唯一形式;方法是消息的序列。

2C和C++动态内存管理不一样

,C语言中用malloc和free函数,c++中除此之外还有new和delete关键字。(关于malloc/free和new/delete的区别又可以说一大堆)

​ new、delete则为C++的操作运算符,它调用的分别为赋值运算符重载operator new()和operator delete();

​ (1)malloc开辟空间类型大小需手动计算,new是由编译器自己计算;

​ (2)malloc返回类型为void*,必须强制类型转换对应类型指针,new则直接返回对应类型指针;

​ (3)malloc开辟内存时返回内存地址要检查判空,因为若它可能开辟失败会返回NULL;new则不用判断,因为内存分配失败时,它会抛出异常bac_alloc,可以使用异常机制;

​ (4)无论释放几个空间大小,free只传递指针,多个对象时delete需加[](原因在第3);

malloc/free为函数只是开辟空间并释放,new/delete则不仅会开辟空间,并调用构造函数和析构函数进行初始化和清理,如下为new/delete、new[]/delete[]实现机制:

而new[]/delete[]则为:

即过程如上,在开辟大小会多开辟四个字节,用于存放对象的个数,在返回地址时则会向后偏移4个字节,而在delete时则会查看内存上对象个数,从而根据个数count确定调用几次析构函数,从而完全清理所有对象占用内存。

所以解释2原因:对于内置类型若new[]但用delete释放时,没有影响,但若是自定义类型如类时,若释放使用 delete时,这时则会只调用一次析构函数,只析构了一个对象,剩下的对象都没有被清理。

4.由上图还可以看出new/delete底层是基于malloc/free来实现的,而malloc/free不能基于new/delete实现;

5.因为new/delete是操作符,它调用operator new / operator delete,它们可以被重载,在标准库里它有8个重载版本;而malloc/free不可以重载;

6.对于malloc分配内存后,若在使用过程中内存分配不够或太多,这时可以使用realloc函数对其进行扩充或缩小,但是new分配好的内存不能这样被直观简单的改变;

7.对于new/delete若内存分配失败,用户可以指定处理函数或重新制定分配器(new_handler(可以在此处进行扩展)),malloc/free用户是不可以处理的。

8.最后一点对于new/delete与malloc/free申请内存位置说明,malloc我们知道它是在堆上分配内存的,但new其实不能说是在堆上,C++中,对new申请内存位置有一个抽象概念,它为自由存储区,它可以在堆上,也可以在静态存储区上分配,这主要取决于operator new实现细节,取决与它在哪里为对象分配空间。

3C语言中没有引用,C++中有引用。(引用和指针的区别)

​ \1. 指针是一个实体,而引用仅是个别名;

​ \2. 引用使用时无需解引用(*),指针需要解引用;

​ \3. 引用只能在定义时被初始化一次,之后不可变;指针可变;

引用“从一而终” _

​ \4. 引用没有 const,指针有 const,const 的指针不可变;

​ \5. 引用不能为空,指针可以为空;

​ \6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为类成员名称时,其占用空间与指针相同4个字节(没找到标准的规定)。

​ \7. 指针和引用的自增(++)运算意义不一样;

4

C语言中不支持函数的重载,C++中支持函数重载,这是依仗C++中不同的名字修饰,例如int fun(int,int)经过名字修饰后变成了_fun_int_int,而C中是_fun,所以C++才会支持不同的参数调用不同的函数。

5

C语言中不能用const修饰的变量定义数组的大小,但是C++中可以。

6

C++中的类是C中所没有的,C中的struct结构体可以在C++中使用,在C++中struct和类的唯一区别在于,struct默认的成员访问修饰符是public,类的默认成员访问修饰符是private。

7

C++中默认的变量链接属性是外链接,而C中是内链接。

8

C++有自己的多态属性,独特的输入输出流等。

\3. 广度优先遍历和深度优先遍历

\4.

\5. tcp的函数

​ socket()函数

connect()函数

bind()函数

listen()函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4vd9ymO-1584948684050)(file:///C:/Users/lenovo/AppData/Local/Temp/msohtmlclip1/01/clip_image003.jpg)]

accept函数

1.套接字创建函数:

int socket(int domain, int type, int protocol)

参数domain:表示要创建套接字的协议族,主要取值:

​ AF_UNIX:创建一个只在本机内进行通信的套接字;

​ AF_INET:使用Ipv4 TCP/IP协议;

​ AF_INET6:使用Ipv6 TCP/IP协议

参数type:表示要创建套接字类型,取值有:

​ SOCK_STREAM:创建一个TCP套接字;

​ SOCK_DGRAM:创建一个UDP套接字;

​ SOCK_RAM:创建一个原始套接字

参数protocol:表示通过参数domain和type指定的套接字类型确定使用的协议;当创建原

始套接字时,系统无法唯一确定协议,此时就需要使用该参数指定所使用的协议。

函数返回值:执行成功返回新创建的套接字,失败返回-1,错误代码存入error。

2.绑定端口函数

int bind(int fd, _CONST_SOCKADDR_ARG addr, socklen_t len)

功能:将一个端口绑定到某个套接字上,该函数常用在服务器端;

参数fd:表示要绑定的(服务器端的)套接字描述符;

参数addr:表示要绑定的(服务器端)IP地址;

参数len:表示要绑定的IP长度

3.监听函数

int listen(int fd, int n);

功能:将一个套接字转化为监听套接字,常用在服务器端监听来自客户端的连接请求;

参数fd:表示监听套接字描述符;

参数n:表示最大监听个数

4.建立连接函数

int connect(int fd, _CONST_SOCKADDR_ARG addr, socklen_t len)

功能:在指定的套接字上创建一个连接;

参数fd:要连接的服务期端的套接字,若该套接字为SOCK_STREAM,则connect向服务器

发起连接请求;

参数addr:要连接的服务器端的IP和端口号;

参数len:表示地址addr长度

**若是TCP连接,只能调用一次connect函数建立连接;若是UDP,则可以多次调用该函数来改变发送数据的目的地址

5.接受连接函数

int accept(int fd, _SOCKADDR_ARG addr, socklen_t *addr_len)

功能:接受来自监听套接字的请求;

参数fd:表示一个监听套接字;

参数addr:表示用来保存发起连接的主机的端口号和IP;

参数addr_len:表示addr长度;

返回值:返回一个和服务器建立连接的客户端的套接字

6.TCP的发送数据函数

​ ssize_t send(int fd, const void *buf, size_t n, int flags)

参数fd:表示建立起连接的套接字(客户端套接字);

参数buf:要发送数据的缓冲区地址;

参数n:发送数据的长度;

参数flags:表示控制选项,一般取0

8.只接受TCP数据函数

ssize_t recv(int fd, void *buf, size_t n, int flags)

参数fd:表示连接套接字(服务器端);

参数buf:表示接受缓冲区;

参数n:表示接受缓冲区大小;

参数flags:一般为0;

9.UDP发送数据函数

int sendto(int fd, const void *buf, size_t n, int flags, _CONST_SOCKADDR_ARG addr, socklen_t addr_len)

参数fd:表示建立起连接的套接字(客户端套接字);

参数buf:要发送数据的缓冲区地址;

参数n:发送数据的长度;

参数flags:表示控制选项,一般取0

参数addr:若该参数非空,则表示不是面向连接的;

参数addr_len:表示addr长度

10.接受数据函数

ssize_t recvfrom(int fd, void *buf, size_t n, int flags, _SOCKADDR_ARG addr, socklen_t *addr_len)

功能:接受TCP或UDP数据;

参数fd:表示连接套接字(服务器端);

参数buf:表示接受缓冲区;

参数n:表示接受缓冲区大小;

参数flags:一般为0;

参数addr:若该参数非空,则表示不是面向连接的;

参数addr_len:表示addr长度

\7. 怎么判断一个double类型是否为0

​ double db;

一般取0

8.只接受TCP数据函数

ssize_t recv(int fd, void *buf, size_t n, int flags)

参数fd:表示连接套接字(服务器端);

参数buf:表示接受缓冲区;

参数n:表示接受缓冲区大小;

参数flags:一般为0;

9.UDP发送数据函数

int sendto(int fd, const void *buf, size_t n, int flags, _CONST_SOCKADDR_ARG addr, socklen_t addr_len)

参数fd:表示建立起连接的套接字(客户端套接字);

参数buf:要发送数据的缓冲区地址;

参数n:发送数据的长度;

参数flags:表示控制选项,一般取0

参数addr:若该参数非空,则表示不是面向连接的;

参数addr_len:表示addr长度

10.接受数据函数

ssize_t recvfrom(int fd, void *buf, size_t n, int flags, _SOCKADDR_ARG addr, socklen_t *addr_len)

功能:接受TCP或UDP数据;

参数fd:表示连接套接字(服务器端);

参数buf:表示接受缓冲区;

参数n:表示接受缓冲区大小;

参数flags:一般为0;

参数addr:若该参数非空,则表示不是面向连接的;

参数addr_len:表示addr长度

\7. 怎么判断一个double类型是否为0

​ double db;

​ if(db>=(-1e-6)&&db<=(1e-6))//1e-6即10的-6次方

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小城微雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值