c - 在一个应用程序中注册回调以在另一个应用程序中检索

标签 c event-handling callback ipc function-pointers

gcc 4.6.0 c89

我有一种客户端服务器应用程序。服务器在事件循环中的一些代码将等待来自客户端的事件。

这不是将使用 UDP/TCP 套接字的客户端服务器。但是客户端和服务器将运行在同一台 linux 机器上。我猜这就像 app1 与在同一台服务器上运行的 app2 对话。

我知道我需要使用函数指针(回调)并且我需要在客户端应用程序中注册回调。服务器将等待来自客户端的事件并采取相应的行动。

所以我在服务器中的设计应该是这样的:

while(running) {
    switch(event) {
        case START_SDL:
        /* DO something */
        break;

        case DELETE_EDL:
        /* Do something */
        break;
    }
}

服务器在循环中运行,等待从客户端接收事件。但是,我不确定如何开始。

非常感谢您的任何建议,

最佳答案

您应该使用工作线程来等待来自主线程的事件并处理它们。这是一个很长的答案,为了避免让它变长,我将省略错误检查,尽管它违反了 the sixth commandment。 .

任务结构和队列

制作一个指定任务的结构。我将使用通用的 get_taskpush_task 函数。 在一个真实的例子中,应该使用 tasks 的线程安全队列,但这会使答案复杂化而毫无用处。我只是从我周围的旧程序中勾画出这个。

struct task {
    /* function callback */
    void (*fun)(void *);
    /* parameter to pass to callback */
    void *arg;
};

同步

使用互斥量来保护任务队列,使用信号量来表示有工作要做。请看我上面用粗体写的内容。

/* this has to be initialized in main */
sem_t sem;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

worker 函数

worker 函数简单地等待并在被告知时执行任务。

static void *worker(void *arg)
{
    struct task t;

    /* detach */
    pthread_detach(pthread_self());

    /* loop forever */
    while (1) {
        /* block until we have work to do */
        sem_wait(&sem);

        /* we've got work to do */
        pthread_mutex_lock(&mtx);
        /* get the task */
        t = get_task();
        pthread_mutex_unlock(&mtx);

        /* we are safe now, nobody can touch t */
        /* execute the callback - here is your function pointer*/
        (*t.fun)(t.arg);
    }
    return NULL;
}

主要功能

main函数的作用是初始化东西和推送任务。

pthread_t t1;

/* initialize unnamed semaphore */
sem_init(&sem, 0, 0);

/* start worker thread */
if (0 != pthread_create(&t1, NULL, worker, NULL)) {
    perror("pthread_create");
    exit(1);
}

推送任务

此时工作线程正在等待您可以从主线程推送的任务。

pthread_mutex_lock(&mtx);
push_task(my_task);
pthread_mutex_unlock(&mtx);

服务器如何知道客户端正在触发事件?那是你自己决定的,在 Unix 上做 IPC 的方法有很多很多。我的建议是使用消息队列

服务器消息队列示例

#define MSGSIZE 1024

int main()
{
    mqd_t mq;
    struct mq_attr attr;
    char message[MSGSIZE];
    int read_bytes;

    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MSGSIZE;

    mq = mq_open("/queue", O_RDWR | O_CREAT, 0700, &attr);
    if ((mqd_t)-1 == mq) {
        perror("mq_open");
        exit(1);
    }

    while (1) {
        /* get message from queue */
        read_bytes = mq_receive(mq, message, MSGSIZE, NULL);
        if (-1 == read_bytes) {
            perror("mq_receive");
            exit(1);
        }

        /* do what you wish with the message */
    }
}

因此,在“做你想做的事”部分,你可以调用解释事件类型并将其推送给工作人员。从客户端发送消息非常相似,所以我不会发布(如果你真的做不到,尽管问)。

这些只是(可能已损坏的)一个大拼图的一部分。你的任务是将它们组装到你正在构建的任何东西中。

关于c - 在一个应用程序中注册回调以在另一个应用程序中检索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5766139/

相关文章:

c++ - C++ 中的多线程事件处理

javascript - 返回一个内部有回调的函数

javascript - 将node-mysql结果行合并为node.js的单个JSON返回

javascript - 停止淡出/淡出事件jquery

javascript - 传递给子组件的事件处理程序(prop)无法调用react native

javascript - 替换 Javascript 中的多个依赖嵌套异步调用 (ECMA 6)

c - 细粒度多线程——一个工作任务应该做多少事情?

c - atoi() 函数如何处理非数字情况?

c - 检查矩阵特殊模式的算法

c - 检查何时没有任何内容通过管道传输到标准输入