1. Socket是什么
学习Socket首先需要了解Socket在整个网络传输中承担怎样的任务,以下是百度对于Socket的解释:套接字(Socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。
由于Linux系统是以文件系统为基础的系统,在对Socket进行操作时,也像对于文件的操作一般(打开、读写、关闭)。
2. Socekt API
int socket( int domain, int type, int protocol)
通过上述socket函数创建一个socket描述符。
2.1 Socket family
socket函数中第一个参数domain意为协议域,亦被称为协议族(参数表示为family),下表展示了能够填充到该参数处的常量值以及其含义。一般的通信是建立在IP协议基础之上的,因此该处参数一般为AF_INET。
Constant | Description |
---|---|
AF_LOCAL | Local communication |
AF_UNIX | Unix domain sockets |
AF_INET | IP version 4 |
AF_INET6 | IP version 6 |
AF_IPX | Novell IPX |
AF_NETLINK | Kernel user interface device |
AF_X25 | Reserved for X.25 project |
AF_AX25 | Amateur Radio AX.25 |
AF_APPLETALK | Appletalk DDP |
AF_PACKET | Low level packet interface |
AF_ALG | Interface to kernel crypto API |
2.2 Socket type
socket函数中第二个参数意为套接字类型,定义了信息传送方式,下表展示了能够填充到该参数处的常量值以及其含义。
Constant | Description |
---|---|
SOCK_STREAM | Stream (connection) socket(TCP) |
SOCK_DGRAM | Datagram (connection-less) socket(UDP) |
SOCK_RAW | RAW socket |
SOCK_RDM | Reliably-delivered message |
SOCK_SEQPACKET | Sequential packet socket |
SOCK_PACKET | Linux specific way of getting packets at the dev level |
这里值得注意的是前三个常量,SOCK_STREAM代表后续将使用数据流来进行数据传输,亦即使用TCP协议;SOCK_DGRAM表示后续将使用数据报来进行数据传输,亦即使用UDP协议;而SOCK_RAW则表示将自定义一种崭新的套接字来进行数据传输。
2.3 Socket Protocol
socket函数中的第三个参数意为套接字发送和接收数据包所使用的协议,下表列举了一些常见的常量及其含义。
Constant | Description |
---|---|
IPPROTO_IP | Dummy protocol |
IPPROTO_TCP | TCP |
IPPROTO_UDP | UDP |
IPPROTO_IPV6 | IPv6 header |
IPPROTO_RAW | Raw IP packets |
此处的参数也不是可以随意填充的,由于我们第一个参数 family 使用的是AF_INET,因此此处只能使用基于IP协议的协议。此外,当第二个参数 type 使用的是SOCK_STREAM时,此处也只能使用IPPROTO_TCP,前者为SOCK_DGRAM时,此处只能是IPPROTO_UDP。
2.4 socket()函数使用
int sockfd = -1;
if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP))<0)
{
printf("sockfd = %d", sockfd);
printf("socket() error!/n");
exit(1);
}
当第二个参数 type 为SOCK_STREAM或SOCK_DGRAM时,参数protocol可以直接为0,此即默认协议。当socket创建成功后,便会返回一个小的正整数值,该值即为该socket的描述符,由sockfd(socket file description)记录。倘若该socket未成功创建,则返回值为-1,此时可以使用perror()函数打印失败原因。
需要注意的是:在使用Raw Socket(即参数 type = SOCK_RAW)时,需要在root用户下执行。