[Linux C编程]网络通信

网络通信

1.简述OSI的七层协议模型以及TCP/IP的四层协议模型

OSI七层模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

TCP/IP(Linux)四层模型:应用层,传输层,网络层,网络接口层

 [Linux C编程]网络通信

2.简述TCP/IP各层的作用

(1)网络接口层(Network Interface Layer):网络接口层是TCP/IP协议软件的最底层,负责将二进制流转换为数据帧,并进行数据帧的发送和接收。数据帧是网络传输的基本单元

(2)网络层(Internet Layer)网络层负责在主机之间的通信中选择数据报的传输路径,即路由。当网络层接收到传输层的请求后,传输某个具有目的地址信息的分组。该层把分组封装在IP数据报中,填入数据报的首部,使用路由算法来确定是直接交付数据报,还是把它传递给路由器,然后把数据报交给适当的网络接口进行传输。

网络层还要负责处理传入的数据报,检验其有效性,使用路由算法来决定应该对数据报进行本地处理还是应该转发。

如果数据报的目的机处于本机所在的网络,该层软件就会除去数据报的首部,再选择适当的运输层协议来处理这个分组。最后,网络层还要根据需要发出和接收ICMP(Internet控制报文协议)差错和控制报文。

(3)传输层(Transport Layer)传输层负责提供应用程序之间的通信服务。这种通信又称为端到端通信。传输层要系统地管理信息的流动,还要提供可靠的传输服务,以确保数据到达无差错、无乱序。为了达到这个目的,传输层协议软件要进行协商,让接收方回送确认信息及让发送方重发丢失的分组。传输层协议软件把要传输的数据流划分为分组,把每个分组连同目的地址交给网络层去发送。

(4)应用层(Application Layer)应用层是分层模型的最高层,在这个最高层中,用户调用应用程序通过TCP/IP互联网来访问可行的服务。与各个传输层协议交互的应用程序负责接收和发送数据。每个应用程序选择适当的传输服务类型,把数据按照传输层的格式要求封装好向下层传输。

3.TCP/IP各层的协议

[Linux C编程]网络通信

第一部分称为网络层。主要包括Internet 协议(IP)、网际控制报文协议(ICMP)和地址解析协议(ARP)

Internet 协议(IP)

 该协议被设计成互联分组交换通信网,以形成一个网际通信环境。它负责在源主机和目的地主机之间传输来自其较高层软件的称为数据报文的数据块,它在源和目的地之间提供非连接型传递服务

网际控制报文协议(ICMP)

 它实际上不是IP层部分,但直接同IP层一起工作,报告网络上的某些出错情况。允许网际路由器传输差错信息或测试报文。

地址解析协议(ARP)

ARP 实际上不是网络层部分,它处于IP和数据链路层之间,它是在32位IP地址和48位物理地址之间执行翻译的协议

第二部分是传输层协议,包括传输控制协议和用户数据报文协议

传输控制协议(TCP):

该协议对建立网络上用户进程之间的对话负责,它确保进程之间的可靠通信,所提供的功能如下:

1.监听输入对话建立请求

2.请求另一网络站点对话

3.可靠的发送和接收数据

4.适度的关闭对话

TCP是重要的传输层协议,目的是允许数据同网络上的其他节点进行可靠的交换。它能提供端口编号的译码,以识别主机的应用程序,而且完成数据的可靠传输TCP 协议具有严格的内装差错检验算法确保数据的完整性TCP 是面向字节的顺序协议,这意味着包内的每个字节被分配一个顺序编号,并分配给每包一个顺序编号

 

用户数据报文协议(UDP):

UDP 提供不可靠的非连接型传输层服务,它允许在源和目的地之间传送数据,而不必在传送数据之前建立对话。它主要用于那些非连接型的应用程序,如:视频点播

UDP也是传输层协议,它是无连接的,不可靠的传输服务.当接收数据时它不向发送方提供确认信息,它不提供输入包的顺序,如果出现丢失包或重份包的情况,也不会向发送方发出差错报文.由于它执行功能时具有较低的开销,因而执行速度比TCP快

 [Linux C编程]网络通信

4.请简述TCP/IP的三次握手的过程

第一步(A->B):主机A向主机B发送一个包含SYN即同步(Synchronize)标志的TCP报文,SYN同步报文会指明客户端使用的端口以及TCP连接的初始序号;

第二步(B->A):主机B在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,表示主机B的请求被接受,同时TCP序号被加一,ACK即确认(Acknowledgement)。

第三步(A->B):主机A也返回一个确认报文ACK给服务器端,同样TCP***被加一,到此一个TCP连接完成

5.TCP和UDP如何选择?

协议的选择应该考虑到数据可靠性、应用的实时性和网络的可靠性。

·对数据可靠性要求高的应用需选择TCP协议,而对数据的可靠性要求不那么高的应用可选

择UDP传送。

·TCP协议中的3次握手、重传确认等手段可以保证数据传输的可靠性,但使用TCP协议会

有较大的时延,因此不适合对实时性要求较高的应用;而UDP协议则有很好的实时性。

·网络状况不是很好的情况下需选用TCP协议(如在广域网等情况),网络状况很好的情况

下选择UDP协议可以减少网络负荷。

6.TCP、UDP的编程模型

 [Linux C编程]网络通信

[Linux C编程]网络通信

 

7.Linux TCP网络编程函数

socket:创建一个socket套接字

bind:绑定IP地址和端口地址到socket

connect:该函数用于绑定之后的客户端到服务器连接

listen:设置能处理的最大连接要求

accept:接收socket连接

send:发送数据

recv:接收数据

 

(1)socket

函数的作用:建立一个新的socket套接字

函数的原型:int socket(int domain,int type,int protocol)

函数的参数:domain:表示使用何种地址类型 AF_INET IPV4

                           AF_INET6 IPV6网络协议

        type:SOCK_STREAM :TCP 面向数据流提供可靠的、面向连接的通讯流

           SOCK_DGRAM:UDP 使用不连续不可信赖的数据包连接

           SOCK_RAM:提供原始网络协议,协议测试

        protocol:指定socket传输协议编号,设为0即可

返回值:成功返回socket套接字描述符,失败-1

头文件:#include<sys/socket.h>

 

(2)bind

函数的作用:绑定IP地址

函数的原型:int bind(int sockfd,struct sockaddr* my_addr,int addrlen)

函数的参数:sockfd:套接字描述符

        my_addr:主机地址        

        struct sockaddr

        {

         u_short sa_family;

         char sa_data[14];

        };

        struct sockaddr_in

        {

           short int sin_family;  /* Internet地址族 */

           unsigned short int sin_port;  /* 端口号 */

           struct in_addr sin_addr;   /* IP地址 */

           unsigned char sin_zero[8];  /* 填0 */

        };

       addrlen:sockaddr的地址长度

返回值:成功0 出错-1

头文件:#include <sys/types.h>

     #include <sys/socket.h>

 

(3)connect

函数的作用:建立socket连接的,通常客户端连接服务器使用

函数的原型:int connect(int sockfd,struct sockaddr* serv_addr,int addrlen)

函数的参数:serv_addr:表示要连接的服务器IP地址

        addrlen:struct sockaddr的长度

返回值:成功0,出错-1

 

(4)listen

函数的作用:聆听网络,等待连接

函数的原型:int listen(int sockfd,int backlog)

函数的参数:sockfd:套接字描述符

        backlog:允许接入的客户端数目

注意:listen并没有连线,只是设置socket的listen模式,真正连接的accept

返回值:成功0 出错 -1

 

(5)accept

函数的作用:接收网络连接,客户端连接,三次握手在这

函数的原型:int send(int sockfd,struct sockaddr * addr, int * addrlen)

函数的参数:addr:连接成功,填充远端客户端的地址

       addrlen:struct sockaddr的长度

返回值:成功返回新的fd,失败-1

 

(6)send

函数的作用:经过socket传送数据,向对方发送数据

函数的原型:int send(int sock_fd,const void *msg,int len,unsigned int flags)

函数的参数: sock_fd:accept建立起来的socket连接描述符,连接远方的IP地址

        msg:发送的数据

        len:数据长度

        flags:设为0

返回值:成功是实际传送出去的字节数,出错-1

 

(7)recv

函数的作用:经过socket接收数据

函数的原型:int recv(int sock_fd,void * buf, int len,unsigned flag);

函数的参数: sock_fd:accept以后socket套接字描述符

        buf:存放地址

        len:接收数据的最大长度

返回值:成功返回接收的字节数,失败-1

 

8.字节序转换函数

不同类型的 CPU 对变量的字节存储顺序可能不同:有的系统是高位在前,低位在后,而有的系统是低位在前,高位在后,而网络传输的数据顺序是一定要统一的。所以当内部字节存储顺序和网络字节顺序不同时,就一定要进行转换

网络字节顺序采用大端排序方式

头文件:#include <arpa/inet.h>

从主机发送到网络(整型数据):

uint32_t htonl(uint32_t hostlong);   //32位数据传送,从主机传送到网络

uint16_t htons(uint16_t hostshort);  //16位数据传送,从主机到网络

从网络到主机:

uint32_t ntohl(uint32_t netlong);   //32位的数据接收,从网络到主机

int16_t ntohs(uint16_t netshort);   //16位的数据接收,从网络到主机

  这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回

 

9.地址格式转化

十进制点分形式转化为二进制格式:inet_addr, inet_pton

(1)inet_addr()

函数的原型:unsigned long int inet_addr(const char *cp)

返回值:成功则返回对应的二进制数据,失败-1

函数的参数:cp:放置如“192.168.1.100”的点分IP地址

 

(2)inet_pton()

函数的原型:int inet_pton(int af,const char *src,void *dest)

函数的参数:af:AF_INET  AF_INET6

        src:点分的要转化的IP地址

返回值:成功1,格式无效0 出错-1

(3)inet_ntop

函数的作用:二进制地址转化成十进制点分形式

函数的原型:const char * inet_ntop(int af,const void* src,socket_t size)

 

10.Linux UDP网络编程函数

(1)sendto

函数的作用:传送socket数据,UDP使用较多

函数的原型:int sendto(int sockfd,void* msg,int len,unsigned int flags,const struct sockaddr * to,int tolen)

函数的参数:sockfd:套接字描述符

        msg:发送的消息内存

        len:消息长度

        toaddr:要发消息的目的地址

        tolen:sizeof(struct sockaddr)

返回值:成功:实际传送的字节数,出错:-1

 

(2)recvfrom

函数的作用:从sockfd接受数据

函数的原型:int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr * fromaddr,int * fromlen)

返回值:成功:返回接收的字节长度   出错:-1

 

补充:

1.五类IP的范围及应用

IP地址分为五类,A类保留给*机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验,各类可容纳的地址数目不同。

其中A类、B类、和C类这三类地址用于TCP/IP节点,其它两类D类和E类被用于特殊用途。

A类地址

⑴ A类地址第1字节为网络地址,其它3个字节为主机地址。

⑵ A类地址范围:1.0.0.1—126.155.255.254

⑶ A类地址中的私有地址和保留地址:

① 10.X.X.X是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。

② 127.X.X.X是保留地址,用做循环测试用的。

B类地址

⑴ B类地址第1字节和第2字节为网络地址,其它2个字节为主机地址。

⑵ B类地址范围:128.0.0.1—191.255.255.254。

⑶ B类地址的私有地址和保留地址

① 172.16.0.0—172.31.255.255是私有地址

② 169.254.X.X是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器。就会得到其中一个IP。

C类地址

⑴ C类地址第1字节、第2字节和第3个字节为网络地址,第4个个字节为主机地址。另外第1个字节的前三位固定为110。

⑵ C类地址范围:192.0.0.1—223.255.255.254。

⑶ C类地址中的私有地址:

192.168.X.X是私有地址。

D类地址

⑴ D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110。

⑵ D类地址范围:224.0.0.1—239.255.255.254

E类地址

⑴ E类地址也不分网络地址和主机地址,它的第1个字节的前五位固定为11110。

⑵ E类地址范围:240.0.0.1—255.255.255.254

 

2.如何让UDP实现可靠传输

自定义通讯协议,在应用层定义一些可靠的协议,比如检测包的顺序,重复包等问题,如果没有收到对方的ACK,重新发包

UDP没有Delievery Garuantee,也没有顺序保证,所以如果你要求你的数据发送与接受既要高效,又要保证有序,收包确认等,你就需要在UDP协议上构建自己的协议。比如RTCP,RTP协议就是在UPD协议之上专门为H.323协议簇上的IP电话设计的一种介于传输层和应用层之间的协议。

 

3.三次握手、四次挥手详细描述过程及作用、优缺点

(建立连接协议)三次握手的过程

(1) 客户端发送一个带SYN标志的TCP报文到服务器,这是三次握手过程中的报文1

(2) 服务器端回应客户端的,这是三次握手过程中的第2个报文,这个报文同时带ACK标志和SYN标志。表示对刚才客户端SYN报文的回应,同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯

(3) 客户必须再次回应服务端一个ACK报文,这是报文3。

三次握手的作用

检测双方的发送和接受能力是否正常

三次握手的优点:

如果未收到客户端的连接确认,服务器就不会建立该连接。从而避免浪费服务器的资源。

三次握手的缺点:

让攻击者有机可趁,通过TCP协议的缺陷,可以发送大量的伪造源地址的攻击报文,不回应ACK包,服务器默认重试五次,就可能造成目标服务器中的队列被占满,阻止其他合法用户进行访问。

 

(连接终止协议)四次挥手的过程

(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)

(2) 服务器收到这个FIN,他发回一个ACK,确认序号为收到的序号加1(报文段5),和SYN一样,一个FIN将占用一个序号

(3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)

(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)

四次挥手的作用

全双工的工作模式下,需要双方均关闭连接

 

4.TCP、UDP的选择

使用TCP:

当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。

在日常生活中,常见使用TCP协议的应用如下:

浏览器,用的HTTP

FlashFXP,用的FTP

Outlook,用的POP、SMTP

Putty,用的Telnet、SSH

QQ文件传输

…………

使用UDP:

当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。

比如,日常生活中,常见使用UDP协议的应用如下:

QQ语音

QQ视频

TFTP

……