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

ant*_*009 10 c ipc function-pointers callback event-handling

gcc 4.6.0 c89
Run Code Online (Sandbox Code Playgroud)

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

这不是将使用UDP/TCP套接字的客户端服务器.但客户端和服务器将在同一台Linux机器上运行.我想就像app1在同一台服务器上运行app2.

我知道我需要使用函数指针(回调),我需要在客户端应用程序中注册回调.服务器将等待来自客户端的事件并相应地执行操作.

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

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

        case DELETE_EDL:
        /* Do something */
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,服务器在循环中运行,等待从客户端接收事件.但是,我不知道如何开始.

非常感谢任何建议,

cni*_*tar 7

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

任务结构和队列

创建一个指定任务的结构.我将使用泛型get_taskpush_task函数.在一个真实的例子中,tasks应该使用线程安全队列,但这会使答案无效.我只用我周围的旧程序草拟了这个.

struct task {
    /* function callback */
    void (*fun)(void *);
    /* parameter to pass to callback */
    void *arg;
};
Run Code Online (Sandbox Code Playgroud)

同步

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

/* this has to be initialized in main */
sem_t sem;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
Run Code Online (Sandbox Code Playgroud)

工人的功能

工作函数只是等待并在执行任务时执行任务.

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;
}
Run Code Online (Sandbox Code Playgroud)

主要功能

主要功能的作用是初始化东西和推送任务.

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);
}
Run Code Online (Sandbox Code Playgroud)

推动任务

此时,工作线程正在等待您可以从main推送的任务.

pthread_mutex_lock(&mtx);
push_task(my_task);
pthread_mutex_unlock(&mtx);
Run Code Online (Sandbox Code Playgroud)

该服务器如何知道客户端正在触发事件?那是由你决定的,在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 */
    }
}
Run Code Online (Sandbox Code Playgroud)

所以在"你想做什么"部分你可以调用解释事件类型并将其推送给工人.从客户端发送消息非常相似,所以我不会发布(如果你真的不能这样做只是问).

这些都只是一个大谜题的(可能已经破碎).你的任务是将它们组装成你正在构建的任何东西.


Mar*_*utz 5

除非这是一项家庭作业,否则我建议使用众多可用的IPC库中的一个,而不是重新发明轮子:

  • IPC就像嵌入式脚本.各种各样的工具可以做到这一点但是每个人都想亲自动手.+1是理智的声音. (2认同)