- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一台用普通C语言编写的服务器,在FreeBSD上使用kqueue接受TCP连接。
接受传入的连接,并将其添加到简单的连接池中,以跟踪文件句柄。
收到数据时(在EVFILT_READ上),我调用recv(),然后将有效负载放入消息队列中,以供其他线程处理。
通过这种方式接收和处理数据非常完美。
处理线程完成后,可能需要将某些内容发送回客户端。由于处理线程可以访问连接池并且可以轻松获取文件句柄,因此我只是从处理线程中调用send()。
这在99%的时间内都有效,但是kqueue时不时地给我一个EV_EOF标志,并断开了连接。
send()的调用频率与EV_EOF错误的数量之间存在明显的相关性,因此由于kqueue线程与处理线程之间的某些竞争状况,我感到EV_EOF。
对send()的调用始终返回预期的字节数,因此我没有填满tx缓冲区。
所以我的问题是; 是否可以按此处所述从单独的线程调用send()?如果没有,那么将数据异步发送回客户端的正确方法是什么?
我发现的所有示例都在与kqueue循环相同的上下文中调用send(),但是我的处理线程可能需要随时发送回数据-即使在从客户端最后一次接收到数据之后几分钟也是如此-显然我无法阻止那个时候的kqueue循环
相关代码段:
void *tcp_srvthread(void *arg)
{
[[...Bunch of declarations...]]
tcp_serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
...
setsockopt(tcp_serversocket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
...
err = bind(tcp_serversocket, (const struct sockaddr*)&sa, sizeof(sa));
...
err = listen(tcp_serversocket, 10);
...
kq = kqueue();
EV_SET(&evSet, tcp_serversocket, EVFILT_READ | EV_CLEAR, EV_ADD, 0, 0, NULL);
...
while(!fTerminated) {
timeout.tv_sec = 2; timeout.tv_nsec = 0;
nev = kevent(kq, &evSet, 0, evList, NLIST, &timeout);
for (i=0; i<nev; i++) {
if (evList[i].ident == tcp_serversocket) { // new connection?
socklen = sizeof(addr);
fd = accept(evList[i].ident, &addr, &socklen); // accept it
if(fd > 0) { // accept ok?
uidx = conn_add(fd, (struct sockaddr_in *)&addr); // Add it to connected controllers
if(uidx >= 0) { // add ok?
EV_SET(&evSet, fd, EVFILT_READ | EV_CLEAR, EV_ADD, 0, 0, (void*)(uint64_t)(0x00E20000 | uidx)); // monitor events from it
if (kevent(kq, &evSet, 1, NULL, 0, NULL) == -1) { // monitor ok?
conn_delete(uidx); // ..no, so delete it from my list also
}
} else { // no room on server?
close(fd);
}
}
else Log(0, "ERR: accept fd=%d", fd);
}
else
if (evList[i].flags & EV_EOF) {
[[ ** THIS IS CALLED SOMETIMES AFTER CALLING SEND - WHY?? ** ]]
uidx = (uint32_t)evList[i].udata;
conn_delete( uidx );
}
else
if (evList[i].filter == EVFILT_READ) {
if((nr = recv(evList[i].ident, buf, sizeof(buf)-2, 0)) > 0) {
uidx = (uint32_t)evList[i].udata;
recv_data(uidx, buf, nr); // This will queue the message for the processing thread
}
}
}
else {
// should not get here.
}
}
}
void *parsethread(void *arg)
{
int len;
tmsg_Queue mq;
char is_ok;
while(!fTerminated) {
if((len = msgrcv(msgRxQ, &mq, sizeof(tmsg_Queue), 0, 0)) > 0) {
if( process_message(mq) ) {
[[ processing will find the uidx of the client and build the return data ]]
send( ctl[uidx].fd, replydata, replydataLen, 0 );
}
}
}
}
最佳答案
EV_EOF
如果在对等方关闭套接字的读取部分后写入套接字,则会收到RST,它会触发EVFILT_READ,并设置EV_EOF。
异步的
您应该尝试aio_read和aio_write。
关于sockets - 使用kqueue异步发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52999294/
使用 kqueue 注册事件时与该事件相关的 ID 提供类型;例如,文件描述符用于标识文件以 watch int kq; struct kevent ke; kq = kqueue(); fd = o
我正在尝试编写一个小程序来发送和接收 UDP 流量并通过 HTTP 接口(interface)接收命令。 HTTP 服务器位于一个 multiprocessing.Process 中; UDP 服务器
我正在尝试使用 kqueue 观察目录大小的变化,这可能吗?这样做的原因是因为我正在监视目录,每当事件触发时,我都会统计目录并比较上次修改时间等,以确定是否发生了内容修改、添加、删除或重命名事件。我的
我使用 kquque 来监控桌面: 标志 - EV_ADD | EV_CLEAR fflags - 注意删除 |注_写 |注意_扩展 |注_属性 |注意_LINK |注意_RENAME | NOTE_
kqueue(在 OS X 上)对读/写常规文件有用吗?我知道 epoll 不对 Linux 上的常规文件有用,所以我想知道 kqueue 是否也是如此。 编辑:我不是说读/写文件,显然 read()
好的:我正在 iPhone OS 应用程序中实现文件共享,当然这意味着文件系统监控。耶! 基本上,当用户将文件操作到 iTunes 中我的应用程序部分时,操作系统会在我可以访问的目录中进行复制和/或删
我正在 mac os x 上使用 Kqueues,并尝试监视文件夹 所以我使用了 EVFILT_VNODE 过滤器,并且我想在删除文件时收到通知,我尝试了 NOTE_DELETE 但它仅检测文件何时通
在 MacOS 中,我使用 O_NONBLOCK 设置了一个读+写套接字来连接到远程服务器。我使用 kqueue 来等待和协调 I/O 事件。对 connect() 的调用立即触发 EINPROGRE
在 mac 上我使用 kqueue,它表明 udata 未更改。但是,kevent 调用的 event_data 返回的数组正在进行一些修改。什么可能导致这种情况?我将指针传递给转换为 void* 的
我在做什么 我正在实现一个基于 python/kqueue (FreeBSD) 的解决方案来跟踪对特定日志文件的更改,当满足 KQ_NOTE_WRITE fflag 时,对文件的更改将由我的 pyth
kqueue mechanism有一个事件标志,EV_RECEIPT ,根据链接的手册页: ... is useful for making bulk changes to a kqueue with
我编写了并发应用程序并发现了错误: buildFdSets: file descriptor out of range 我发现这是一个进程中文件描述符数量的操作系统限制,在我的 FreeBSD 中是
我很难理解如何将 kqueue 用于用户空间事件。 我寻找 2 个用例。 用例 1:手动重置事件 用例 2:自动重置事件 我想我了解如何使用 kqueue() 和 kevent(),但我不清楚传递给
我正在学习有关 kqueue 的教程(特别是 http://eradman.com/posts/kqueue-tcp.html 和 https://wiki.netbsd.org/tutorials/
我知道,如果远程主机优雅地关闭连接,epoll将报告EPOLLIN,并且调用read或recv不会阻塞,并且将返回0字节(即流结束)。 但是,如果连接未正常关闭,并且 write 或 send 操作失
我的开发机器是 MacBook(当然有 kqueue)。然而,在生产环境中,我们运行的是 Linux(当然使用 epoll)。显然,要了解我的代码的性能特征,我需要使用 epoll 运行它。也就是说,
如果一个线程(比如 X)正在等待 epoll_wait(),另一个线程(比如 Y)是否可以调用 epoll_ctl() 来注册对文件的兴趣描述符 9。之前在线程X中调用epoll_wait()能否返回
我正在努力在 epoll 和 kqueue 标志之间画一条平行线,特别是 EPOLLONESHOT EPOLLET EPOLLEXCLUSIVE 和 EV_CLEAR/EV_DISPATCH/EV_O
Python Epoll 有一个名为 epoll.unregister 的函数,它从 epoll 对象中删除已注册的文件描述符。有谁知道Kqueue中与此类似的功能是什么。对于 kqueue 我只能找
我试图了解 kqueue 中 EV_DISABLE 和 EV_ENABLE 的用例。 int KQueue = kqueue(); struct kevent ev = { .ident = fd
我是一名优秀的程序员,十分优秀!