套接字(socket)是一种通讯机制,凭借这种机制,客户/服务器系统的开发工作既可以在本地单机上运行,也可以跨网络运行。
创建套接字
socket系统调用创建一个套接字返回一个描述符,该描述符可以用来访问该套接字
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
创建的套接字是一条通信线路的一个端点。domain参数自定协议族,type参数指定套接字的通信类型,protocol参数指定使用的协议。
domain信号可指定的协议族:
域 | 说明 |
AF_UNIX | UNIX域协议(文件系统套接字) |
AF_INET | ARPA因特网协议(UNIX网络套接字) |
AF_ISO | ISO标准协议 |
AF_NS | 施乐(Xerox)网络系统协议 |
AF_IPX | Novell IPX协议 |
AF_APPLETALK | Appletalk DDS |
AF_UNIX和AF_INET前者用于通过UNIX和Linux文件系统实现本地套接字后者用于UNIX网络套接字。
type指定用于指定套接字的特性,取值包括SOCK_STREAM和SOCK_DGRAM,对于AF_INET域来说 TCP、UDP
protocol该参数设置为0,表示默认协议。
套接字地址
每个套接字域都有自己的地址格式。对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件sys/un.h
struct sockaddr_un{
sa_family_t sun_family; /*AF_UNIX*/
char sun_path[]; /*pathname*/
}
linux中sun_path路径名的长度限制为108个字符,因为地址结构长度不一致,所以许多套接字调用需要用到一个复制特定地址长度变量或将它作为一个输出。
在AF_INET域中,套接字地址由结构sockaddr_in来指定,该结构定义在头文件netinet/in.h中,它至少包含以下接成员:
struct sockaddr_in{
short int sin_family; /*AF_INET*/
unsigned short int sin_port; /*Port number*/
struct in_addr sin_port; /*Internet address*/
}
struct in_addr{
unsigned long int s_addr;
}
命名套接字
创建的套接字要想被其它进程使用,服务器程序就必须给套接字命名,AF_UNIX关联到一个文件系统的路径名,AF_INET会关联到一个IP的端口号。
#include <sys/socket.h>
int bind(int socket, const struct sockaddr * address, size_t address_len);
bind系统调用把参数address中的地址分配给文件描述符socket关联的未命名套接字。地址结构的长度由address_len传递。
地址的长度和格式取决于地址族。bind调用需要将一个特定的地址结构指针转换为指向通用地地址类型(struct sockaddr *)。
创建套接字队列
为了能够在套接字上接收进入的连接,服务器程序必须创建一个队列来保护未处理的请。它用listen系统调用来完成这一工作。
#include <sys/socket.h>
int listen(int socket, int backlog);
参数backlog用于对队列中未处理的连接数做限制
接收连接
一旦服务器程序创建并命名套接字后,之后就可以通过accept系统调用来等待客户对该套接字的连接。
#include <sys/scoket.h>
int accept(int socket, struct sockaddr *address, size_t *address_len);
accpet系统调用只有当有客户程序试图连接到有socket参数指定的套接字上时才返回。这里的客户是指,在套接字队列中排在第一个未处理连接。accept函数函数将创建一个新的套接字来与该客户进行通信,并且返回新套接字的描述符。
请求连接
客户程序通过一个未命名的套接字和服务器监听套接字之间建立建立连接的方法来连接到服务器。它们通过connect调用来完成这一工作。
#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address, size_t address_len);
参数socket指定的套接字将连接到参数address指定的服务器套接字,address指向结构体的长度由address_len指定,参数socket指定的套接字必须通过socket调用获得的一个有效的文件描述符。
成功时,connect调用返回0,失败时返回-1。
关闭套接字
可以通过close函数来终止服务器和客户上的套接字连接。