你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

【Linux】套接字相关接口详解

2021/11/27 11:21:55

文章目录

      • 套接字相关接口
        • (一)创建套接字socket
        • (二)套接字地址
        • (三)命名套接字bind
        • (四)创建监听队列(套接字队列)listen
        • (五)接收连接accept
        • (六)请求连接connect
        • (七)关闭套接字

套接字相关接口

(一)创建套接字socket

  • socket系统调用创建一个套接字并返回一个文件描述符,使用该文件描述符可以访问该套接字。
  • 头文件:sys/types.h sys/socket.h

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

  • domain : 指定协议族
说明
AF_UNIXUNIX域协议(文件系统套接字)
AF_INETARPA因特网协议(UNIX网络套接字)
AF_ISOISO标准协议
AF_NS施乐(Xerox)网络系统协议
AF_IPXNovell IPX协议
AF_APPLETALKAppletalk DDS
  • type : 取值包括SOCK_STREAMSOCK_DGRAM

    • SOCK_STREAM有序可靠的面向连接的双向字节流、对于AF_INET域套接字来说,默认是通过TCP连接进行双向传递,TCP协议提供的分片和重组长消息,重传网络中丢失的数据
    • SOCK_DGRAM数据报服务,发送最大长度(固定)的消息,无法保证乱序的情况,对于AF_INET域来说,默认是UDP数据报提供
  • protocol : 一般由套接字域和套接字类型来与决定

    • 0为默认协议
  • 返回值:成功返回一个文件描述符,失败-1


(二)套接字地址

  • AF_UNIX域套接字地址结构体
    头文件sys/un.h
struct sockaddr_un
{
	sa_family_t sum_family;		//AF_UNIX(short int 类型、sys/un.h中声明)
	char 		sun_path[];		//路径套接字文件名
};
  • AF_INET域套接字的地址结构体
    头文件:
    netinet/in.h
struct sockaddr_in
{
	short int 			sin_family;	//AF_INET
	unsigned short int 	sin_port;	//端口号
	struct in_addr 		sin_addr;	//ip网络地址结构体
};

IP地址结构:

struct in_addr
{
	unsigned long int s_addr;	//4字节,32位的值
}

(三)命名套接字bind

bind系统调用把参数address中的地址分配给文件描述符sokcet关联的未命名套接字
bind调用需要将一个特定的地址结构指针转换为指向通用地址类型struct sockaddr*
int bind(int socket, const struct sockaddr* address, size_t address_len);
返回值:成功0,失败-1并设置errno错误码

errno值说明
EBADF文件描述符无效
ENOTSOCK文件描述符对应的不是套接字
EINVAL文件描述符对应的套接字已被命名
EADDRNOTAVAIL地址不可用
EADDRINUSE地址已经绑定一个套接字

AF_UNIX域其他的错误码

errno值说明
EACCESS权限不足,无法创建文件系统的路径文件名
ENOTDIR、ENAMETOOLONG文件名不符合要求

(四)创建监听队列(套接字队列)listen

为了套接字能够接受进入的连接,服务器必须创建一个队列来保存未处理的连接请求。
int listen(int socket, int backlog);

  • backlog : 监听队列的长度,常用数值5;(当监听队列中的连接请求大于这个数时,后面的请求将会被拒绝)
  • 返回值:成功0,失败-1。errno值EBADF、EINVAL、ENOTSOCK与bind的错误代码含义相同

(五)接收连接accept

使用accept来接收监听队列中的客户端对该套接字的连接请求(当监听队列为空,没有客户端的连接请求时,该方法会阻塞block
int accept(int socket, struct sockaddr* address, size_t* address_len);

  • address : 该指针指向一个保存客户端地址的结构体变量中,若不需要客户端的地址信息,可以置为NULL
  • address_len :指定客户端的结构长度,超过这个值将会被截断
  • 返回值:成功返回新套接字文件描述符,监听队列没有未处理的请求时,将会阻塞block;

int flags = fcntl(socket, F_GETFL, 0);
fcntl(socket, F_SETFL, O_NONBLOCK | flags);
可以修改套接字,设置O_NONBLOCK标志(非阻塞),实现发生错误accept返回-1
错误情况大部分与bind、listen类似,EWOULDBLOCK(没有未处理链接时的错误)和EINTR(accept阻塞时,执行被中断而产生的错误)


(六)请求连接connect

客户端通过在一个未命名的套接字和服务器监听套接字之间建立连接的方法连接到服务器。

(个人理解:用一个未命名的套接字去连接指定的套接字,类似于你打电话给你的好朋友,你的好朋友在看着电话等着你打给他,你首先得有电话,再知道对方的电话号码,这里的socket就是你的电话,address就是对方的号码,而connect就是拨打电话的过程)

int connect(int socket, const struct sockaddr* address, size_t address_len);

  • socket : 通过socket系统调用创建的未命名套接字
  • address : 指定服务器的套接字的地址信息
  • 返回值:成功0,失败-1并设置errno
errno值说明
EBADF传递给socket参数的文件描述符无效
EALREADY该套接字已有正在进行的连接
ETIMEDOUT连接超时
ECONNREFUSED连接被拒绝

注意:

  • 连接没有立马建立,将会被阻塞一段时间
  • 超时时间到达,连接被放弃,connect调用失败
    在这里插入图片描述

(七)关闭套接字

  • 类似于文件描述符,打开一个文件,使用完毕后,必须要关闭文件描述符,close函数来中止连接,服务器和客户端都因该关闭;
  • 对于服务器来说,read返回0时(说明客户端关闭了连接),关闭客户端的套接字

注意:

  • 若套接字是面向连接的,并设置了SOCK_LINGER选项,close调用会该套接字还有数据传输时阻塞