程序员社区

socket网络编程知识

1 sockaddr和sockaddr_in

这两个结构体都用来处理网络通信的地址


sockaddr在头文件<sys/socket.h>中定义,它的缺陷是sa_data将目标地址和端口混在了一起,其具体定义如下:

struct sockaddr{
	sa_family_t sin_family;		;地址族
	char sa_data[14];14字节,包括socket中的目标地址和端口信息
}

sockaddr_in在头文件netinet/in.harpa/inet.h中定义,该结构体解决了sockaddr的缺陷,将port和addr分开储存在两个变量中,其定义如下:

struct sockaddr_in{
	sa_family_t      sin_family;		//地址族
	uint16_t         sin_port;			//16位TCP/UDP端口号
	struct in_addr   sin_addr;			//32位IP地址
	char             sin_zero[8];		//不使用

该结构体中提到的另一个结构体in_addr定义如下,它用来存放32位IP地址:

struct in_addr{
	In_addr_t		s_addr;				//32位IPv4地址
}

sin_port和sin_addr都必须是网络字节序(NBO),一般可视化的数字都是主机字节序(HBO)。


对比

两者长度一样,都是16个字节,即占用内存的大小是一致的,因此可以互相转化。两者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。

sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址。

sockaddr_in是Internet环境下socket的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数。即,sockaddr_in用于socket定义和赋值,sockaddr用于函数参数。


htons()和inet_addr()

htons()的作用是将端口号由主机字节序转换为网络字节序的整数值(host to net)。

inet_addr()的作用是将一个IP字符串转化为一个网络字节序的整数值,用于sockaddr_in.sin_addr.s_addr。

inet_ntoa()的作用是将一个sin_addr结构体输出成IP字符串(network to ascⅡ)。

htonl()作用和htons()一样,不过它针对的是32位的(long),而htons()针对的是16位的(short)。

与htonl()和htons()作用相反的两个函数是ntohl()和ntohs()。

2 socket()函数介绍

函数原型:

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

这个函数建议一个协议族为domain、协议类型为type、协议编号为protocol的套接字文件描述符。如果函数调用成功,会返回一个标识这个套接字的文件描述符,失败的时候返回-1。


domain

这个参数用于设置网络通信的域,函数socket()根据这个参数选择通信协议的族。通信协议族在文件sys/socket.h中定义。

domain的值及含义如下表所示:

名称 含义
PF_UNIX, PF_local 本地通信
AF_INET, PF_INET IPv4网络协议
PF_INET6 IPv6网络协议
PF_IPX IPX-NoveⅡ协议
PF_NETLINK 内核用户界面设备
PF_X25 ITU-T X25 / ISO-8208协议
PF_AX25 Amateur radio AX.25
PF_ATMPVC 原始ATM PVC访问
PF_APPLETALK Appletalk
PF_PACKET 底层包访问

type

用于设置套接字通信的类型,主要值及对应解释如下:

名称 含义
SOCK_STREAM Tcp连接,提供序列化的、可靠的、双向连接的字节流。支持带外数据传输
SOCK_DGRAM 支持UDP连接(无连接状态的消息)
SOCK_SEQPACKET 序列化包,提供一个序列化的、可靠的、双向的基本连接的数据传输通道,数据长度定长。每次调用读系统调用时数据需要将全部数据读出
SOCK_RAW RAW类型,提供原始网络协议访问
SOCK_RDM 提供可靠的数据报文,不过可能数据会有乱序
SOCK_PACKET 这是一个专用类型,不能呢过在通用程序中使用

注意,并不是所有的协议族都实现了这些协议类型,例如,AF_INET协议族就没有实现SOCK_SEQPACKET协议类型。


protocol

这个参数用于指定某个协议的特定类型,即type类型的某个类型。通常某协议中只有一种特定类型,这样protocol参数仅能设置为0;但是有些协议有多种特定的类型,就需要设置这个参数来选择特定的类型。


errno

函数socket()并不总是执行成功,有可能会出现错误,错误的产生有多种原因,可以通过errno获得:

含义
EACCES 没有权限建立指定的domain的type的socket
EAFNOSUPPORT 不支持所给的地址类型
EINVAL 不支持此协议或者协议不可用
EMFILE 进程文件表溢出
ENFILE 已经达到系统允许打开的文件数量,打开文件过多
ENOBUFS/ENOMEM 内存不足。socket只有到资源足够或者有进程释放内存
EPROTONOSUPPORT 指定的协议type在domain中不存在
赞(0) 打赏
未经允许不得转载:IDEA激活码 » socket网络编程知识

一个分享Java & Python知识的社区