面试题答案
一键面试1. 异步I/O模型简介
异步I/O模型允许应用程序在执行I/O操作时,不必等待操作完成,可以继续执行其他任务。当I/O操作完成后,系统会通过回调函数或事件通知应用程序。
2. 设备与服务器连接建立过程
-
初始化套接字:
- 在设备端和服务器端都需要创建套接字。在C语言中,可以使用
socket
函数。
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
AF_INET
表示使用IPv4地址族,SOCK_STREAM
表示使用TCP协议。
- 在设备端和服务器端都需要创建套接字。在C语言中,可以使用
-
绑定地址:
- 服务器端需要绑定一个特定的地址和端口,以便设备能够连接到它。使用
bind
函数。
struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERVER_PORT); servaddr.sin_addr.s_addr = INADDR_ANY; bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
htons
函数将主机字节序转换为网络字节序,INADDR_ANY
表示接受任意IP地址的连接。
- 服务器端需要绑定一个特定的地址和端口,以便设备能够连接到它。使用
-
监听连接:
- 服务器端调用
listen
函数开始监听连接请求。
listen(sockfd, BACKLOG);
BACKLOG
表示等待连接队列的最大长度。
- 服务器端调用
-
异步连接:
- 在设备端,使用异步I/O函数(如
aio_connect
在Linux下)来发起连接请求。 - 首先创建一个
aiocb
结构体,用于存储异步I/O操作的控制块。
struct aiocb my_aiocb; memset(&my_aiocb, 0, sizeof(struct aiocb)); my_aiocb.aio_fildes = sockfd; struct sockaddr_in servaddr; servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr); my_aiocb.aio_addr = (struct sockaddr *)&servaddr; my_aiocb.aio_nbytes = 0;
- 然后调用
aio_connect
发起异步连接。
int ret = aio_connect(&my_aiocb);
- 应用程序可以继续执行其他任务,当连接完成时,通过
aio_error
和aio_return
函数获取连接结果。
while (aio_error(&my_aiocb) == EINPROGRESS); int connect_ret = aio_return(&my_aiocb); if (connect_ret == 0) { // 连接成功 } else { // 连接失败 }
- 在设备端,使用异步I/O函数(如
-
接受连接(服务器端):
- 服务器端使用异步接受连接的方式,例如在Linux下可以使用
epoll
机制结合accept4
函数。 - 首先创建一个
epoll
实例。
int epollfd = epoll_create1(0);
- 将监听套接字添加到
epoll
实例中。
struct epoll_event ev; ev.data.fd = sockfd; ev.events = EPOLLIN; epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev);
- 然后在事件循环中处理连接事件。
struct epoll_event events[MAX_EVENTS]; int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); for (int i = 0; i < nfds; ++i) { if (events[i].data.fd == sockfd) { int connfd = accept4(sockfd, NULL, NULL, SOCK_NONBLOCK); // 处理新连接 } }
- 服务器端使用异步接受连接的方式,例如在Linux下可以使用
3. 关键数据结构
- 套接字地址结构:如
struct sockaddr_in
,用于存储IP地址和端口信息。 - 异步I/O控制块:如
struct aiocb
,用于管理异步I/O操作。 - epoll事件结构:如
struct epoll_event
,用于epoll
机制中存储事件和对应的文件描述符。