欢迎光临seo外链资源网站,我们为你英文友情链接的信息及服务

seo外链资源

一个资源好的推广优化外链发布网站,为你解决外链获客难题

从 0 开始学习 Linux 系列之「26.网络编程基础 」

作者:jcmp      发布时间:2021-05-06      浏览量:0
网络编程基础概念网络编程中有许多基础概念

网络编程基础概念

网络编程中有许多基础概念必须了解,比如 OSI,TCP/IP,字节序列等,这些都是开发网络应用的基础,可以帮助我们更好的理解网络程序的工作原理,来一起学习下一些比较重要的概念。

OSI 开放系统互联模型

OSI ( Open System Interconnection )是国际标准化组织(ISO)制定的 计算机互联的标准,是设计和描述计算机网络通信的基本框架 。OSI 模型把网络通信分为 7 层,如下图所示:

OSI 模型的设计目的是成为一个所有销售商都能实现的开放网络模型,来克服使用众多私有网络模型所带来的困难和低效性,我们熟知的 TCP/IP 协议也是以 OSI 为基础的。

TCP/IP 协议簇体系结构

TCP/IP 协议是在 OSI 模型之上开发的通信协议,简化为 4 层:

TCP/IP 协议没有表示层和会话层,其中每层对应到 OSI 的协议主要有下面这些:

我们经常见到如:HTTP,TCP,UDP,IP,来了解下其中比较常用的 TCP 和 UDP 协议。

TCP/IP 协议基础

TCP/IP 包含许多协议,比如 TCP,UDP,IP,HTTP,FTP 等,平常上网都会使用到它们,必须要了解些概念:

网络编程中主要使用 TCP 和 UDP 的概念,这里介绍这 2 者,先来看看 TCP 协议。

1. TCP 协议

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议 ,它有如下的特点:

2. UDP 协议

UDP(User Datagram Protocol)的简称,即是 用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务 ,它有如下特点:

TCP 和 UDP 的区别

两者主要有 5 点区别:

TCP/IP 通信过程

两台主机使用 TCP/IP 相关的协议通信的基本过程是:假设应用层使用的是 HTTP 协议,除物理层是实际传输数据外,其他对等层只是虚拟通信,对等层一般需要遵循相同的协议,每一层传输数据只与相邻的上下层有关系。TCP 层及以下是由操作系统内核实现,是处理通信细节,而应用程序是通过 socket 来处理应用程序网络通信的细节。如下图所示:

TCP/IP 数据包

通信过程中传输的是一个个的数据包,因为通信协议包含许多层,所以数据包在每一层都会进行相关的处理。以 TCP 数据包为例,最后的数据包含有多个部分:

数据包在传输到达目的主机后又会反向解析(从下到上去掉头部信息),最后只剩下用户数据发给指定程序。

Socket 简介

Socket 套接字是由 BSD(加州大学伯克利分校软件研发中心)开发的 一套独立于具体协议的网络编程接口 ,应用程序可以用这个接口进行网络通信。但 Socket 实际上还是属于进程间通信(IPC),因为网络通信实质上是不同机器上的进程之间的通信。Socket 接口主要有下面这些特征:

5 种 Socket 类型

在使用 socket 接口进行编程时, 必须明确所使用的 socket 类型 ,主要有 5 种类型:

IP 地址和端口号

在 Socket 网络编程中经常使用下面的结构体来定义要连接的 IP 和端口:

struct sockaddr_in { // 地址家族,常用 AF_INET 代表 TCP/IP 协议簇 short int sin_family; // 端口号,网络字节序 unsigned short int sin_port; // IP 地址,网络字节序 struct in_addr sin_addr;}// IP 地址的结构定义typedef uint32_t in_addr_t;struct in_addr { in_addr_t s_addr;};

具体的代码初始化方法会在下一篇的 Web 服务器项目中介绍,这里以概念为主。

网络字节序

不同的机器在网络上以字节流的方式来传输数据,必须要保证数据从一端传输到另一端能够解析成原来的样子,但是不同的机器的字节序是不同的,所以在进行网络传输的时候必须统一传输的字节序。 网络字节序是 TCP/IP 中规定好的一种数据表示格式 ,它与具体的 CPU 类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释, 网络字节顺序采用 big endian(大端)排序方式 。

这里再介绍下机器的字节序:

例如,在内存中存储 0x01020304 的 2 种方式,括号中是内存地址 0x1000 - 0x1003:

端口字节序转换

在使用 socket 进行网络编程时要将 IP 和端口在网络字节序和主机字节序间相互转换,例如下面的端口字节序转换函数:

#include // host to net long 主机序 -> 网络序uint32_t htonl(uint32_t hostlong);// host to net short 主机序 -> 网络序uint16_t htons(uint16_t hostshort);// net to host long 网络序 -> 主机序uint32_t ntohl(uint32_t netlong);// net to host short 网络序 -> 主机序uint16_t ntohs(uint16_t netshort);

例如将端口 1234 转换成网络字节序的代码如下:

struct sockaddr_in myaddr;// convert to net portmyaddr.sin_port = htons(1234);// convert to host portuint16_t port = ntohs(myaddr.sin_port);

IP 字节序转换

IP 字节序转换函数将 IP 字符串和对应的整数值相互转换,名称的命名与端口转换函数类似:

#include #include #include // inet address to networkint inet_aton(const char *cp, struct in_addr *inp);// inet network to addresschar *inet_ntoa(struct in_addr in);// convert to network ipin_addr_t inet_addr(const char *cp);

例如转换 IP:192.168.0.1 的代码如下:

struct in_addr my_addr;// convert to network numberinet_aton("192.168.0.1", &my_addr);// convert to address stringchar *ip_string = inet_ntoa(my_addr);// convert "127.0.0.1"struct sockaddr_in client_addr;client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

域名和 IP 地址之间的转换

有时候需要通过网站的域名来获取它的 IP 地址,这时候就要用到下面的转换函数:

#include /* * name: 是域名字符串,例如 "www.baidu.com" * return: 域名结构体 */struct hostent *gethostbyname(const char *name);struct hostent { char *h_name; /* 地址名称 */ char **h_aliases; /* 地址别名 */ int h_addrtype; /* 地址类型 */ int h_length; /* ip 地址长度 */ char **h_addr_list; /* ip 地址数组,一个域名可能对应多个 IP */}// 第一个 IP 地址#define h_addr h_addr_list[0]

例如根据百度域名来获取它的 IP:

// 获取百度的域名结构struct hostent* baidu_host = gethostbyname("www.baidu.com");// 获取第一个百度 IPstruct in_addr baidu_addr;baidu_addr.s_addr = (uint32_t)(baidu_host->h_addr);// 转换成主机地址char *baidu_ip_addr = inet_ntoa(baidu_addr);

结语

关于 Linux 网络编程基础还有很多概念,本次主要介绍了一些很重要和很常见的点,这些技术点在实际的编程中都会使用到,所以必须要掌握。对于想要系统学习计算机网络的同学可以参考谢希任老师的《计算机网络》一书。

那么本次就介绍到这里,我们下次再见 :)