对于我的应用程序,我需要一个负责与许多客户端进程交互的中央进程。客户端进程需要一种方法来识别中央进程并与之通信。此外,中央进程可能没有运行,客户端进程需要一种方法来识别该事实。这个应用程序将在类Unix系统上运行,所以我考虑使用命名管道套接字来完成任务。具体来说,我将如何使用命名管道套接字执行此任务(实际代码将不胜感激!)?如果命名管道套接字不理想,是否有更好的替代方案?
答案 0 :(得分:6)
命名管道并不是非常理想的 - 它们最适合单读者,单作家情况。
然而,UNIX域套接字非常适合它。它们使用套接字API,端点名称是文件系统条目(与命名管道一样)。
这是一个非常简单的示例(您当然希望添加大量的错误检查!)。首先是服务器端:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCKNAME "/tmp/foo"
int main()
{
int s1, s2;
int i;
struct sockaddr_un sa = { AF_UNIX, SOCKNAME };
unlink(SOCKNAME);
s1 = socket(AF_UNIX, SOCK_STREAM, 0);
bind(s1, (struct sockaddr *)&sa, sizeof sa);
listen(s1, 5);
for (i = 0; i < 10; i++)
{
struct sockaddr_un sa_client;
socklen_t sa_len = sizeof sa_client;
FILE *f;
s2 = accept(s1, (struct sockaddr *)&sa_client, &sa_len);
f = fdopen(s2, "r+");
fprintf(f, "Hello, you are client number %d\n", i + 1);
fclose(f);
}
return 0;
}
现在是客户端:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCKNAME "/tmp/foo"
int main()
{
int s1;
struct sockaddr_un sa = { AF_UNIX, SOCKNAME };
FILE *f;
char buffer[1024];
s1 = socket(AF_UNIX, SOCK_STREAM, 0);
connect(s1, (struct sockaddr *)&sa, sizeof sa);
f = fdopen(s1, "r+");
while (fgets(buffer, sizeof buffer, f) != NULL)
{
printf("Message received: %s", buffer);
}
fclose(f);
return 0;
}
请注意,您应该在/var/run/yourappname
而不是/tmp
下创建套接字。
man 7 unix
是进一步调查的好资源。
答案 1 :(得分:0)
这是一个已经使用数据库的应用程序吗?如果是这样,我会使用它而不是添加另一个完整的通信媒体。
答案 2 :(得分:0)
D-Bus提供面向对象的IPC,另外还包括一个激活功能,如果服务器进程尚未运行,它将启动服务器进程。缺点是网络封装基本上是DIY。
答案 3 :(得分:0)
您需要阅读有关该主题的标准教科书之一 - 可能是Stevens'UNIX Network Programming, Vol 1, 3rd Edn'。
你必须做出一些决定,包括:
这些决定从根本上影响了所需的代码。如果进程一次处理一条短消息,则考虑UDP而不是TCP可能是合适的。如果该过程正在处理与几个通讯员的扩展对话并且不会让孩子处理它们,那么您可以考虑线程编程是否合适。如果没有,您需要考虑及时性以及中央流程是否可以无限期地保留。
如评论所示,您还需要考虑流程应如何处理未运行的中央流程 - 您需要考虑响应应该有多快。您还必须防止中央进程如此忙碌以至于它看起来没有运行,即使它正在运行但只是非常忙于处理其他连接。如果无法连接到中央进程的进程尝试启动它的新副本,您会遇到多少麻烦。
答案 4 :(得分:0)
根据你问题中的信息,听起来你正在构建一个分布式系统,它有一个中央消息传递总线,组件用于通信。我建议使用TCP套接字,原因如下: