欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unix网络编程【2】-套接口操作函数

程序员文章站 2022-07-14 20:33:45
...

本博客参考自《Unix网络编程卷1》

套接字操作函数

1.字节排序函数

一个16位的整数,由两个字节组成。它在计算机中有两种存储方式:1.将低字节作为起始地址-小端序。2.将高字节作为起始地址-大端序。
Unix网络编程【2】-套接口操作函数
MSB(most significant bit):做高有效位。LSB(least significant bit)-最低有效位

一般的intelCPU都是按照小端序存储数据,而网络通信中一般要求大端序。可用下面的程序判断系统的字节序。

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
	union {
	  short  s;
      char   c[sizeof(short)];
    } un;
	un.s = 0x0102;
	if (sizeof(short) == 2) {
		if (un.c[0] == 1 && un.c[1] == 2)
			printf("big-endian\n");
		else if (un.c[0] == 2 && un.c[1] == 1)
			printf("little-endian\n");
		else
			printf("unknown\n");
	} else
		printf("sizeof(short) = %d\n", sizeof(short));
	exit(0);
}

本人Ubuntu系统运行的结果:
Unix网络编程【2】-套接口操作函数

对上述程序的说明:程序采用union结构共享内存,通过使用不同的方式解读内存,获得主机的大端、小端信息。

在编写网络通信程序时,通常需要在大端和小端序之间转换,以下几个函数可以实现这些功能

Ubuntu:/usr/include/netinet/in.h
#include <netinet/in.h>
uint16_t	htons(uint16_t host16bitvalue);
uint32_t	htonl(uint32_t host32bitvalue);
uint16_t	ntohs(unit16_t net16bitvalue);
uint32_t	ntohl(uint32_t net32bitvalue);

其中h-host,n-network,s-short,l-long。其中前两个函数传入主机字节返回网络字节。后两个函数传入网络字节返回主机字节。s结尾代表对16位端口操作,l结尾代表对32位IP地址操作。

2.字节操纵函数

字节操纵函数主要的作用是对指针指向的多字节内存进行清零、拷贝和比较的操作。这些函数著有有两类:一类是以b开头的,一类是以mem开头的。

Ubuntu:/usr/include/strings.h
#include<strings.h>
void bzero(void *dest,size_t ntytes);
void bcopy(const void*src,void*dst,size_t nbytes);
int bcmp(const void* ptr1, const void* ptr2,size_t nbytes)

bzero-把目标字节串中指定数目的字节置0.

bcopy-将指定数目的字节从源字节串移到目标字节串。

bcmp-比较两个任意字节串,相同返回0,否则返回非0.

Ubuntu:/usr/include/string.h
#include <string.h>
void *memset(void *dest,int c,size_t len);
void *memcpy(void *dest, const void *src,size_t nbytes);
int memcmp(const void *ptrl,const void *ptr2,size_t nbytes)

memset-将目标字节串指定数目的字节置为c。

memcpy-类似与bcopy,不过两个指针的顺序相反。当源字节串与目标字节串重叠时,需要用memmove代替memcpy。

memcmp-比较两个任意字符串,ptr1>ptr2返回大于0。ptr1 == ptr2 返回0。ptr1 < ptr2返回小于0。字节比较从第一个字节开始,直到出现第一个不等的字节。

3.IP地址转换函数

在编写网络程序时,通常需要在点分十进制串(127.0.0.1)与网络字节二进制之间转换,下面介绍进行转换的函数

IPv4版本

Ubuntu:/usr/include/arpa/inet.h
#include <arpa/inet.h>
int inet_aton(const char *strptr,struct in_addr *addrptr);
in_addr_t inet_addr(const char *strptr);
char *inet_ntoa(struct in_addr inaddr);

inet_aton-将strptr所指C字符串转换成一个32位网络字节序二进制值,通过addrptr来存储。成功返回1,否则返回0.

inet_addr-将点分十进制字符串转换为32位网络字节序二进制,通过返回值返回。INADDR_NONE=255.255.255.255用于指示错误。这就意味着255.255.255.255不能通过该函数处理。此函数现在基本已经废弃。

inet_ntoa-将一个32位的网络字节序二进制IPv4转换成相应的点分十进制数串。

IPv4和IPv6通用版本

Ubuntu:/usr/include/arpa/inet.h
#include <arpa/inet.h>
int inet_pton(int family,const char *strptr,void *addrptr);
const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);

函数中p和n分别代表presentation和numeric。其中family参数有两个选项AF_INET和AF_IENT6,如果以不支持的协议族调用,函数会将errno置为EAFNOSUPPORT.

inet_pton-将strptr指针所指定的字符串,转换为对应的二进制结果并存放在addrptr指针所指的内存区域。若成功返回1,输入格式无效返回0,出错返回-1.

inet_ntop-将数值格式(addrptr)转换为对应的表达格式(strptr)。len用于指定目标存储单元大小。如果len过小,errno会被置为ENOSPC。strptr不可以为空指针,调用者需要分配内存。调用成功这个指针就是函数返回值。

对5个转换函数的总结
Unix网络编程【2】-套接口操作函数

IPv6地址一共128位,16位之间有个“:”。

IPv4兼容的IPv6或者映射的IPv6,前6个16位正常表达,后2个16位表达成IPv4的表达格式。