首页 > 代码库 > 网络编程基础

网络编程基础

网络编程基础

1、套接字概念

Linux环境下使用套接字进行进程之间的通信。用过套接字的接口,其他进程的位置对于应用程序来讲是透明的。相互通信双方端点都有一个套接字,双方如果要进行通信,通过套接字建立桥梁,双方就可以通信了。

类似文件一样,套接字也有一个套接字描述符,应用程序可以像操作文件一样操作套接字。在进行网络通信的过程中,用户感觉就是在操作文件一样,这是Linux将外部设备抽象为一个文件的好处。

2、字节序

不同主机的体系结构不同,所采用的数据存储方式不同。网络中,进程之间的通信是跨主机的,这样会出现字节序不一样的问题。为了能够解决好这个问题,网络协议提供一种字节序,无论主机是什么字节序,在进行网络传输的时候,先转换成网络字节序,到接收端再对应主机转换字节序。

Linux环境下使用下面四个函数进行字节序转换:

uint32_t  htonl(uint32_t hostint32);是将主机字节序转换成网络字节序,参数是32位本地主机数据。

uint16_t  htons(uint16_t hostint16); 是将主机字节序转换成网络字节序,参数是16位本地主机数据。

uint32_t  ntohl(uint32_t hostint32); 是将网络字节序转换成主机字节序,参数是32位本地主机数据。

uint16_t  ntohs(uint16_t hostint16); 是将网络字节序转换成主机字节序,参数是16位本地主机数据。

3、地址格式

网络环境中每一个主机都有一个唯一标识自己的地址,这个地址就是IP地址,IP地址由一个32位的整数组成,每8位作为一个独立的数字,用“.”分开。例如:192.168.1.1,“.”与“.”之间时8位,因此最大值是225。

Linux中使用in_addr结构表示一个IP地址,结构体定义如下:

struct in_addr

{

        in_addr_t       s_addr;          // in_addr_t被定义为无符号整形

}

Linux中的网络通信地址格式

struct sockaddr_in

{

        sa_family_t    sin_family;      ///16位的地址族

       in_port_t       sin_port;        ///16位的端口号

        struct in_addr        sin_addr; ///32位的IP地址

        unsigned char sin_zero[8];   ///填充区,8个字节填“0”

}

该结构体中最后一个成员表示填充区,保证sockaddr_in正好16个字节。这样的目的是为了socketaddr_in结构可以和sockaddr地址结构可以随意转换。Socketaddr结构体定义如下:

struct socketaddr

{

       sa_family sa_family;             ///16位地址族

       char sa_data[14];                 ///14字节的填充

}

这两个结构体定义等长,socketaddr结构中的sa_data成员实际可以看成是由sin_port、sin_addr、sin_zero这三个成员变量组成的。

4、地址形式转换

IP地址是以二进制的形式存储在地址结构中的,观察不方便,因此需要转化成点分十进制表示IP地址更加直观,可以使用下面的函数进行格式转换。

const char * inet_ntop(int domain, const void * restrict addr,  char * restrict str, socklen_t size);是将二进制地址转换为字符串形式的地址,成功返回首地址,二进制格式错误返回0,函数错误返回-1。’

inti net_pton(int domain, const char * restrict str, void * restrict addr);是将字符串形式的地址转换成二进制形式的地址。

上述两个函数中,domain参数值可以是AF_INET或者是AF_INET6分别表示IPv4协议或者IPv6协议。

5、地址映射

对于用户来说,套接字的结构信息是不必要的,用户只需要传递一个sockaddr_in地址结构的地址,之后由系统填充就可以了。

网络环境中服务器需要提供一个唯一的IP地址和一个主机名(域名)。对于大多数服务器来说,客户端往往不知道其准确的IP地址,只知道域名,这种情况下用户可以求助于DNS服务器。该服务器可以将域名转换成IP地址。

转换后的IP地址和端口号存储在一个addrinfo的地址信息结构中,Linux环境下提供一个函数,根据用户指定的服务器域名和服务器名称得打服务器的IP地址和端口号,并写到一个sockaddr_in地址结构中。函数如下:

int fetaddrinfo(const char * restrict host, const char * restrict service, const struct addrinfo * restrict hint, struct addrinfo ** restrict res);

函数中前两个参数表示需要访问的主机名和服务的名称。这两个名称应该都已经在DNS服务器中注册过。第三个参数表示一个过滤地址模板,一般设置为NULL,第4个参数表示一个地址信息结构列表。该表列出来所有可能的符合条件的地址结构,用户可以从中任选一个作为通信的地址。如果成功得到地址信息列表,函数返回0,失败返回-1。

 

网络编程基础