gpt4 book ai didi

c - PostgreSQL 使用 epoll_wait 异步连接

转载 作者:太空狗 更新时间:2023-10-29 12:13:01 24 4
gpt4 key购买 nike

我想在我的 Linux 项目中异步使用 PostgreSQL (9.1)。为此,我必须使用 epoll_wait(因为应用程序的其他部分)。目标是最终在边沿触发模式下使用 epoll。但是我无法使连接过程正常工作,即使在非边缘触发模式下也是如此。我不知道为什么。但是,当用户名和密码正确时,它将起作用。但它也必须在密码错误时起作用。在那种情况下,我会得到一些我不明白的错误。 :-/这是我使用的代码(连接已经用 PQconnectStart() 初始化,参数列表与 PQconnectdb() 一起工作):

void ConnectDB(PGconn * connection)
{
int pq_fd = PQsocket(connection);
int epoll_fd = epoll_create1(0);
struct epoll_event event;
struct epoll_event *eventList = (epoll_event *)calloc(64, sizeof(epoll_event));

event.data.fd = pq_fd;
event.events = EPOLLOUT | EPOLLERR;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pq_fd, &event);

while (true) {
PostgresPollingStatusType pt = PQconnectPoll(connection);
switch (pt)
{
case PGRES_POLLING_OK:
printf("*** connection established!\n");
return;

case PGRES_POLLING_FAILED:
printf("*** connection failed: %s\n", PQerrorMessage(connection));
return;

case PGRES_POLLING_ACTIVE:
printf(" --- poll result: PGRES_POLLING_ACTIVE\n");
break;

case PGRES_POLLING_READING:
printf(" --- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN\n");
event.events = EPOLLIN | EPOLLERR;
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
break;

case PGRES_POLLING_WRITING:
printf(" --- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT\n");
event.events = EPOLLOUT | EPOLLERR;
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
break;
}

int n = epoll_wait(epoll_fd, eventList, 64, -1);
if (n == -1) {
printf("epoll_wait() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
}
}

这是我得到的输出:

--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
epoll_ctl() error: 2: No such file or directory

有人有想法吗?

最佳答案

postgresql 客户端库首先尝试 ssl 连接,如果失败,它会在没有 ssl 的情况下重试。这与连接失败的原因无关为什么,并且根本没有通知调用者。因此,即使错误是错误的密码,客户​​端库也会关闭文件描述符并重新打开明文的套接字连接。

如果一个文件描述符被关闭,它会自动从 epoll-set 中删除(这会导致您的“没有这样的文件或目录”错误消息)。所以你必须手动重新添加它:

if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
if (errno == ENOENT) {
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, PQsocket(connection), &event);
} else {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
}

另一种选择是永久启用或禁用 ssl,为此将 sslmode=requiresslmode=disable 添加到您的连接字符串中。但是,如果您打算使用 PGreset()(或遇到套接字关闭并重新打开对调用者透明的任何其他情况),那么您将遇到同样的问题。

诚然,postgresql-client-library 的这种行为对 epoll() 不是很友好。在过去,当使用 select()poll() 时,这不是问题,因为内核中没有像 epoll( ) 现在。

关于c - PostgreSQL 使用 epoll_wait 异步连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35184780/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com