应用程序设计(6)之linux网络编程基础 tcp/udp

前面的进程间通信最后一个socket是网络方面的知识,现在来引入网络的基础概念吧。

一.网络基础篇

Internet历史:

1.1957年,前苏联卫星上天

2.1958年,美国建立ARPA(国防部高级研究计划署)

3.1968年,ARPA提出 资源共享计算机网络,简称ARPAnet,“阿帕网”,实现互联不同的计算机

4.早期的ARPAnet使用的网络控制协议NCP(network control procotol)。

TCP/IP 协议:Internet中的“世界语”。

1.TCP:用来检测网络传输中的出错,并具备一定的纠错能力。

2.IP协议:实现互联网不同类型的操作系统和计算机的网络连接。

网络体系结构

 由于网络是非常复杂的,因此采用分而治之的方法设计。

因此网络体系结构是指 网络的层次结构和每层使用的协议的集合。

OSI体系结构:七层模型,理想化的模型,尚未完成实现。

1.应用层:主要是对一些应用程序,获得要传输的数据。

2.表示层:对数据进行 格式定义,加密或者 转换。

3.会话层:建立通信进程的 逻辑名字和物理名字之间的联系。

4.传输层:提供可靠数据传输,差错处理及恢复(TCP),流量控制(UDP)。

5.网络层:数组分组.路由选择。

6.数据链路层:数据组成  可发送和  接收的帧

7.物理层:传输物理信号等,硬件层面。

应用程序设计(6)之linux网络编程基础 tcp/udp_第1张图片

与七层有关的例子:

1.两路交换机:用到数据链路层的交换(硬件)

2.三路交换机:网络层的交换(软件)

TCP/IP体系结构:Internet 事实上的工业标准

1.应用层:负责处理特定的应用程序细节,应用层面面向不同的网络应用引入不同的应用层协议

常用协议(http:超文本传输,ftp:文件传输,dns:域名解析协议,SMTP:邮件传输协议)

2.传输层:确定数据包交给主机上的哪个任务

常用协议(TCP.UDP)

3.网络层:实现端到端的传输

常用协议(IP:互联网络.ICMP:互联网络控制管理协议ping.IGMP:广播.组播)

4.网络接口和物理层:屏蔽硬件差异,向上层提供统一的接口

常用协议(ARP:地址解析协议   IP地址:MAC地址

                  RARP:逆地址解析协议  MAC地址:IP地址)

 TCP/IP协议族

应用程序设计(6)之linux网络编程基础 tcp/udp_第2张图片

TCP/IP协议通信模型

应用程序设计(6)之linux网络编程基础 tcp/udp_第3张图片

TCP/IP协议:

1.MTU(max transform unit):最大传输单元,1500字节

2.MSS(maxitum segment size):最大报文长度【app header + user data=1460】

TCP协议和UDP协议

1.TCP协议:传输控制协议,面向连接,数据安全可靠(数据无失序.无重复.无丢失)

        常用场景:密码传输QQ,微信的登陆注册

                          大量的数据传输

特点:面向连接,建立连接管道,因此数据传输效率相对较低

2.UDP协议:传输控制协议,无连接,不保证数据的安全可靠性

        常用场景:少量图片数据传输

                          音视频,媒体流量数据传输

                          无线网络

                           广播.组播通信

特点:由于无连接,不用建立连接管道,因此数据传输效率相对高。

OSI模型和TCP/IP对应:

应用程序设计(6)之linux网络编程基础 tcp/udp_第4张图片

应用程序设计(6)之linux网络编程基础 tcp/udp_第5张图片

二.网络编程基础篇

预备知识

1.socket

        (1)独立于具体协议的网络编程接口

        (2)在OSI模型中,主要在会话层和传输层

        (3)是一个文件描述符(套接字)

        (4)可用于TCP.UDP.IPX通信

2.socket的类型

       (1)流式套接字(SOCK_STREAM):提供一种面向连接的服务,用于TCP传输控制协议

       (2)数据报套接字(SOCK_DGRAM):提供无连接的服务,用于UDP通信。

       (3)原始套接字(SOCK_RAW):提供底层通信(IP.ICMP.IGMP)

         应用程序设计(6)之linux网络编程基础 tcp/udp_第6张图片

 3.IP地址:网路中标识主机的编号,常以点分形式存在(例如“192.168.2.177”)

       1.IPV4地址:整个ip占32位,每段8位表示0-255

        IPV6地址:  整个ip占128位 

       2.  ip地址组成: 网络号 + 主机号  列如“192.168.2”+“177”

                                               其中“2”表示网段号,也就是在哪个路由网络中(网络号+1)

       3.网络ip分类:主要ip的第一段前8位数据组成

A类网:0~127              子网掩码:255.0.0.0

B类网:128~191           子网掩码:255.255.0.0

C类网:192~223          子网掩码:255.255.255.0

D类网:224~239 组播地址

E类网:240~255保留测试地址

       4.私有IP地址范围

应用程序设计(6)之linux网络编程基础 tcp/udp_第7张图片

         5.子网掩码 :例如:255.255.255.255.0(c类网)

         6.已知,计算机网络号:ip&(umask)=“192.168.2.177”&((255.255.255.0))=“192.168.2”

                          主机号: ip&(~umask)=“192.168.2.177”&(~(255.255.255.0))=“177”

注意:这是c类网的例题

4.由于网络中识别2进制的数据,因此ip地址必须进行转换  

1.将代码字符串的ip地址转换成 网络字节序 二进制,并返回转换后的地址
			in_addr_t inet_addr(const char *strptr);
			头文件:
				#include 
			参数:
				strptr:代码中的字符串 ip(主机字节序的ip地址)
			返回值:
				成功:返回网络字节序二进制的首地址 
		2、将网络字节序的二进制 转换成 主机字节序的 ip
			char *inet_ntoa(stuct in_addr inaddr);
			头文件:
				#include 
			参数:
				inaddr:网络字节序的 ip地址
			返回值:
				成功:主机字节序的 ip字符串 首地址。

5.字节序:数据的存储顺序(方式)

小端序:低序字节存储低地址

Ubuntu采用小端序,也就是主机字节序

大端序:低序字节存储高地址

网络采用大端序,也就是网络字节序

例如:0x1122  ————>11 高字节        

6.端口号:在主机中标识处理网络数据的进程,也就是进程ID号

总所周知端口号:1~1023                             (用户一般不能使用)

已登记的端口号:1024~49151

动态端口号: 49152~65535

 (1)主机字序转网络字节序

        

u_long htonl(int port);  	//host to network long
			u_short htons(int port);    //host to network short

 (2)网络字节序转主机字节序

u_long ntohl(u_long hostlong); 		//network to host long
			u_short ntohs(u_short hostshort);	//network to host short

 7.

客户端:与用户进行数据交互的界面程序,即  上位机。

服务器:为客户端提供数据服务的后台软件。

8.基于 tcp的服务器编程流程(框架)

(1)创建套接字 socket()

(2)绑定   bind()

(3)监听 listen()

(4)接受连接 accept()

(5)数据交互 recv/send read/write

(6)关闭  close()

9.api接口

(1)函数原型socket()

1、函数原型:
			int socket(int domain, int type, int procotol);
			功能:
				创建套接字,打开网卡设备,设置套接字类型
			头文件:
				#include 
				#include 
			参数:
				domain:	ip地址协议族  AF_INET(ipv4协议)
				type  :	套接字类型 	  SOCK_STREAM
				protocol:	通常为  0
			返回值:
				成功:返回套接字(网卡的文件描述符)
				失败:返回-1,并设置错误信息

  (2)    函数原型bind()

int bind(int sockfd, struct sockaddr *addr, size_t size);
			功能:
				将ip地址、端口号 与 套接字进行绑定,将ip和端口共享到网络中。
			头文件:
				同上
			参数:
				sockfd:	套接字,socket函数成功的返回值
				addr  :	通用协议地址结构体的首地址
				size  :	结构体的大小
			返回值:
				成功:返回 0
				失败:返回-1,并设置错误信息
				
			通用协议地址结构体:
				struct sockaddr {
				   sa_family_t sa_family; 		//地址协议族 AF_INET
				   char        sa_data[14];
			    }
				
			Internet协议地址结构体:
				struct sockaddr_in {
				   sa_family_t    sin_family; /* address family: AF_INET */
				   in_port_t      sin_port;   /* port in network byte order */
				   struct in_addr sin_addr;   /* internet address */
			    };

			    /* Internet address. */
			    struct in_addr {
				   uint32_t       s_addr;     /* address in network byte order */
			    };
				
			结构体头文件: #include 
			
			填写ip地址和端口号
				struct sockaddr_in addr;
				addr.sin_family		 = AF_INET;
				addr.sin_port 		 = htons(9527);
				// INADDR_ANY (0.0.0.0) means any address  for  binding;
				addr.sin_addr.s_addr = inet_addr("0.0.0.0");

(3)函数原型listen()

int listen(int sockfd, int backlog);
			功能:
				设置监听套接字,设置 客户端连接请求队列的长度,
				也就是设置同一时刻能接受的最大请求数。
				
				监听完成就是启动服务器,套接字变成监听套接字
			参数:
				sockfd:套接字
				backlog:请求队列的长度,在内核中开辟的。
			返回值:
				成功:返回 0
				失败:返回-1,并设置错误信息
				

(4)函数原型accept()

int accept(int sockfd, struct sockaddr *addr, socklen_t *len);
			功能:
				阻塞等待,接受客户端连接,建立通信管道。
				如果 请求队列中没有客户端的请求,该函数就阻塞。有就立即接受连接,建立通道。
			参数:
				sockfd:监听套接字
				addr  :结构体首地址(存储连接成功的客户端ip、端口号的结构体首地址)
				len	  :存储结构体的大小(存储客户端信息的结构体首地址)
			返回值:
				成功:返回连接套接字(通信管道的id号),标识成功的客户端。
				失败:返回-1,并设置错误信息
			注意:
				1、如果不需要保存客户端ip地址和端口号,则第2、3参数 传递 NULL。
				2、该函数调用一次 就只能接受一个 客户端连接

(5)数据交互

read()

函数原型:
				ssize_t read(int connfd, void *buf, size_t size);
				参数:
					connfd:连接套接字(通信管道id)
					
			

recv()

ssize_t recv(int connfd, void *buf, size_t len, int flags);
				参数:
					flags:阻塞与非阻塞模式,通常0表示阻塞。
				
				注意:
					1、read读数据,默认为阻塞模式,如果读缓冲区有数据立即返回,无数据就等待
					2、recv读数据可以设置 模式
					3、当 连接断开时,read或recv立即返回 0值
					

write()

ssize_t write(int connfd, void *buf, size_t size);
				参数:
					connfd:连接套接字(通信管道id)
				
				ssize_t send(int connfd, void *buf, size_t len, int flags);
				参数:
					flags:阻塞与非阻塞模式,通常0表示阻塞。
					

(6)int close()

int close(int sockfd);

你可能感兴趣的:(应用程序设计,linux,网络,c语言,开发语言)