sockaddr是在头文件 /usr/include/bits/socket.h 中定义的,如下:
/* Structure describing a generic socket address. */
struct sockaddr
{
__SOCKADDR_COMMON (sa_); //field: sa_family
char sa_data[14]; /* Address data. */
};
而sockaddr_in是在头文件 /usr/include/netinet/in.h 中定义的,如下:
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); // field: sin_family
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
其中__SOCKADDR_COMMON宏在/usr/include/bits/sockaddr.h中定义,如下:
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
#endif
二者的占用的内存大小是一致的,因此可以互相转化,从bit意义上说,他们并无区别。
sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址。一般情况下sockaddr是系统调用的参数,程序员编写的程序中并不直接针对此数据结构操作,而是使用sockaddr_in,调用系统调用的时候需要将sockaddr_in强制转换成sockaddr在传入系统调用。sockaddr_in 是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。
#include
#include
int socket(int domain, int type, int protocol);
creates an endpoint for communication and returns a descriptor.
domain: 指定协议簇/协议域。可用的协议簇定义在linux/socket.h中。
Name Purpose Man page
PF_UNIX, PF_LOCAL Local communication unix(7)
PF_INET IPv4 Internet protocols ip(7)
PF_INET6 IPv6 Internet protocols
PF_IPX IPX - Novell protocols
PF_NETLINK Kernel user interface device netlink(7)
PF_X25 ITU-T X.25 / ISO-8208 protocol x25(7)
PF_AX25 Amateur radio AX.25 protocol
PF_ATMPVC Access to raw ATM PVCs
PF_APPLETALK Appletalk ddp(7)
PF_PACKET Low level packet interface packet(7)
注意domain是PF_XXX,其中PF=protocol familiy是协议簇的意思, 而AF_XXX中AF=address family是地址簇的意思。据说是最开始的时候设计者设想一个AF可以支持多个PF,后来就没有后来了,所以目前PF_XXX和AF_XXX是等效的。
type: 套接口类型,指明通信语义,目前支持如下通信语义
SOCK_STREAM
Provides sequenced, reliable, two-way, connection-based byte streams. An out-of-band
data transmission mechanism may be supported.
SOCK_DGRAM
Supports datagrams (connectionless, unreliable messages of a fixed maximum length).
SOCK_SEQPACKET
Provides a sequenced, reliable, two-way connection-based data transmission path for
datagrams of fixed maximum length; a consumer is required to read an entire packet with
each read system call.
SOCK_RAW
Provides raw network protocol access.
SOCK_RDM
Provides a reliable datagram layer that does not guarantee ordering.
SOCK_PACKET
Obsolete and should not be used in new programs; see packet(7).
一般TCP使用SOCK_STREAM,UDP使用SOCK_DGRAM。
protocol:
一般设置为0.
Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes. They do not preserve record boundaries. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a connect(2) call. Once connected, data may be transferred using read(2) and write(2) calls or some variant of the send(2) and recv(2) calls. When a session has been completed a close(2) may be performed. Out-of-band data may also be transmitted as described in send(2) and received as described in recv(2).
The communications protocols which implement a SOCK_STREAM ensure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, then the connection is considered to be dead. When SO_KEEPALIVE is enabled on the socket the protocol checks in a protocol-specific manner if the other end is still alive. A SIGPIPE signal is raised if a process sends or receives on a broken stream; this causes naive processes, which do not handle the signal, to exit. SOCK_SEQPACKET sockets employ the same system calls as SOCK_STREAM sockets. The only difference is that read(2) calls will return only the amount of data requested, and any remaining in the arriving packet will be discarded. Also all message boundaries in incoming datagrams are preserved.
return value
-1 if error occurs; fd else success