UNIX-Linux socket网络编程(上):基本概念

一、基本概念

OSI模型与TCP/IP模型:

OSI(开放系统互联参考模型)为计算机网络设计的一个通信模型,由于太过复杂而没有完全实现,仅仅是一套设计方案。
共分为七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

TCP/IP模型是OSI的具体实现,只实现出一部分,还没有完全实现,还有一些漏洞不太安全,是我们目前使用通信模型。

TCP/IP也叫协议簇,由一堆网络通信协议组成,其中TCP、IP是最重要的两个协议,因此简称TCP/IP。

    共分为四层:
        物理层:负责通过网络收发数据包
        网络层:选择、流量控制,网络拥塞问题,IP协议是该层的核心协议
        传输层:在机器之间建立用于会话的连接,UDP/TCP是该层的核心协议
        应用层:主要为用户提供针对性的服务,该层的代表协议有:HTTP、SMTP、FTP、TELNET、POP、SNMP

    对应关系:
    OSI                    		TCP/IP
    会话层、表示层、应用层 		 应用层
    传输层                 		 传输层
    网络层               		 网络层
    物理层、数据链路层    		 物理层

UDP:面向无连接的通信,也叫用户数据报通信,就是发短信。

		速度快、但不够安全,有数据丢失的可能性。
        目标地址+数据包 直接发送,对方是否收到、数据有没有丢失,发送都是不知道的。

TCP:面向连接的通信,就是像是打开电话。

        与UDP相比速度有些慢,但数据绝对不会丢失。
        连接时的三次握手,数据包校验、重传、断开时的四次挥手来确保数据不会丢失。

IP地址
在计算机网络有每计算机都必须有一个唯一的标识符(身份证号)IP地址,是IP协议在工作是需要的一个标识,在同一个作用域下是唯一的。
由4个0~255的整数组成,一般采用点分10进制表示,在计算机中用32位二进制存储。

公有IP和私有IP:
    公有IP:在网络服务提供商登记过的IP地址叫公有IP,可以在互联网被访问到。
    私有IP:公司、家庭的局域网中自己分配的IP地址,不能网络中被访问。
    注意:私有IP主动访问公有IP,公有IP可以按原路返回数据,私有IP想与私有IP进行通信需要借助一个公有IP(服务器)

子网掩码:由4个0~255之间的整数组成,一般采用点分十进制表示。
子网掩码&IP地址 = 网络地址,网络地址相同说明在同一个子网内,这样就可以直接通信而不需要服务器。

网关地址:
负责出入口的计算机,一般由路由器担任(路由器就是一台具有路由功能的计算机)。

端口号:
IP地址代表通信的计算机,端口代表计算机的进程。
每个网络通信的进程都需要一个独一无二(当前系统中)编号,区分与哪个进程通信。
1~1024大多数已经被操作系统占用,我们在编程时一般使用1024以上的端口号。

二、套接字

socket是一种接口机制(ip、UDP/TCP、端口号),负责进程与进程间的连接通信。
相关函数:

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

功能:创建一个socket对象
domain:
AF_INET 采用IPv4版本的ip地址通信。
AF_UNIX、AF_LOCAL 本地间的进程通信,还通过网络,仅仅是当前系统中的进程间通信。
type:
SOCK_STREAM 数据流协议 TCP
SOCK_DGRAM 数据报协议 UDP
protocol:特殊的通信协议,一般不使用,给0即可。
返回值:代表socket对象的描述符,失败返回-1。

准备通信地址:
    // 基本地址 接口中使用的都是这种类型
    struct sockaddr {
        sa_family_t sa_family; //地址族
        char        sa_data[14]; //14字节,包含套接字中的目标地址和端口信息
    }

    // 网络通信地址
    struct sockaddr_in {
        __kernel_sa_family_t  sin_family; 与socket中的domain参数保持一致即可
        __be16        sin_port; 端口号
        struct in_addr    sin_addr;   ip地址,是一个四字节整数
    };

    // 本地通信地址
    struct sockaddr_un {
        __kernel_sa_family_t sun_family; 与socket中的domain参数保持一致即可
        char sun_path[UNIX_PATH_MAX]; socket文件的路径
    };

】 注意:在使用时需要把网络通信地址、本地通信地址强制转换成基本地址

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:将套接字与通信地址绑定。
sockfd:代表套接字的描述符。
addr:通信地址,需要转换。
addrlen:通信地址的字节数,bind函数就是依靠字节数来判断是本地通信地址还是网络通信地址。

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

功能:连接通信对方的socket对象。

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

功能:从socket接收消息,TCP专用,也可以使用read代替

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

功能:向socket发送消息,TCP专用,也可以使用write代替
flags:是否阻塞,一般写0,代表阻塞。

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

功能:从socket接收消息,UDP专用
sockfd:socket描述符
buf:存储数据的缓冲区
len:缓冲区的大小
flags:是否阻塞,一般写0
src_addr:接收发送方的来时的地址
addrlen:地址结构体的字节数,用于区别是哪种地址

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

功能:向socket发送消息,UDP专用
sockfd:socket描述符
buf:存储待发送的数据的首地址
len:要发送的数据字节数
flags:是否阻塞,一般写0
dest_addr:目标地址
addrlen:地址结构体的字节数,用于区别是哪种地址

大小端:一般的个人计算机采用的小端系统,而网络字节序是大端

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);

功能:把本地字节转换成网络字节序

uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

功能:把网络字节序转换成本地字节序

in_addr_t inet_addr(const char *cp);

功能:把点分十进制的字符串转换成网络字节序的32位整数

char *inet_ntoa(struct in_addr in);

功能:把网络字节序的32位整数转换成点分十进制的字符串

三、UDP通信的编程模型

UDP

本地通信
进程A 进程B
创建套接字 创建套接字
准备地址A 准备地址B
绑定地址A 绑定地址B
接收数据+返回地址 发送数据+地址A
发送数据 接收数据
关闭套接字 关闭套接字
网络通信
进程A 进程B
创建套接字 创建套接字
准备地址 准备目标地址
绑定地址
接收数据 发送数据+地址
发送数据 接收数据
关闭套接字 关闭套接字

注意:一对一通信。

四、TCP通信编程模型

TCP

服务器 客户端
创建套接字 创建套接字
准备地址 准备目标地址
绑定地址
监听 连接服务器
等待连接
分配进程线程进行服务
接收数据 发送数据
发送数据 接收数据
关闭套接字 关闭套接字
int listen(int sockfd, int backlog);

功能:设置多少个客户端可以处在排队状态

int accept(int sockfd, struct sockaddr *addr, socklen_t *);

功能:等待客户端连接
addr:输入型参数,获取客户端的地址
addrlen:获取地址的字节数

由于TCP是面向连接的通信,如果长时间没有数据发送,该连接可能会断掉。
解决方案:客户端定时向服务端发送无用的数据包(心跳包)。

在Linux、UNIX系统下recv、send可以使用read、write代替,但是windows不支持该函数。

猜你喜欢

转载自blog.csdn.net/perror_0/article/details/106756707