我有用C语言编写的单线程服务器,它接受基于EPOLL的TCP / UDP连接,并支持我们需要支持的众多协议层的插件。这一点很好。
由于单线程特性,我想实现一个数据库层,该层可以使用相同的EPOLL架构,而不是分别迭代所有打开的连接。
我们在其API中使用MariaDB和支持非阻塞功能的MariaDB连接器。
https://mariadb.com/kb/en/mariadb/using-the-non-blocking-library/
但我发现的并不是我的预期,我期待的内容如下所述。
首先我触发mysql_real_connect_start()
,如果它返回零,我们立即调度查询,因为这表明不需要阻塞,尽管这种情况从未发生过。
否则,我获取似乎是立即的文件描述符并将其注册到EPOLL并保释回主EPOLL循环等待事件。
s = mysql_get_socket(mysql);
if(s > 0)
{
brt_socket_set_fds(endpoint, s);
struct epoll_event event;
event.data.fd = s;
event.events = EPOLLRDHUP | EPOLLIN | EPOLLET | EPOLLOUT;
s = epoll_ctl(efd, EPOLL_CTL_ADD, s, &event);
if (s == -1) {
syslog(LOG_ERR, "brd_db : epoll error.");
// handle error.
}
...
所以,过了一段时间后,我确实得到EPOLLOUT,表明套接字已被打开。
我尽职尽责地调用mysql_real_connect_cont()但是在这个阶段它仍然返回一个非零值,表明我必须等待更长时间?
但那是我得到的最后一次EPOLL事件,除了EPOLLRDHUP,我猜MariaDB在10秒后挂断。
任何人都可以帮助我理解这个想法是否可行吗?
谢谢......谢谢......非常感谢。
答案 0 :(得分:1)
对于那些降落在这里的人来说没关系,我修好了它,或者说没有破坏它。
请注意 - 从示例中 - _start / _cont调用返回的状态作为参数传递给下一个_cont。事实证明这是至关重要的。
状态包含标志MYSQL_WAIT_READ,MYSQL_WAIT_WRITE,MYSQL_WAIT_EXCEPT,MYSQL_WAIT_TIMEOUT,如果没有传递给下一个_cont,我猜你是在搞乱_cont状态机。
我没有在调用_start和_cont的不同地方之间保存状态。
struct MC
{
MYSQL *mysql;
int status;
} MC;
...
// Initial call
mc->status = mysql_real_connect_start(&ret, mc->mysql, host, user, password, NULL, 0, NULL, 0);
// EPOLL raised calls.
mc->status = mysql_real_connect_cont(&ret, mc->mysql, mc->status);
if(mc->status) return... // keep waiting check for errors.