对于我的应用程序,我需要一个负责与许多客户端进程交互的中央进程。客户端进程需要一种识别和与中央进程通信的方法。此外,中央进程可能没有运行,客户端进程需要一种识别这一事实的方法。由于该应用程序将在类Unix系统上运行,因此我考虑使用套接字(sockets)来完成任务。我应该如何具体地使用套接字来完成这个任务(非常感谢提供实际代码!)?如果套接字不是最理想的选择,是否有更好的替代方案?
命名管道并不是最理想的选择,它们最适合单读单写的情况。
而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
是进一步调查的好资源。这是一个已经使用数据库的应用程序吗?如果是,我会使用它而不是添加另一个全新的通信媒介。
D-Bus 提供面向对象的 IPC,还包括一个激活功能,如果服务器进程尚未运行,则会启动它。缺点是网络封装基本上是自己动手。
你需要阅读该领域的标准教材之一,可能是Stevens的 'UNIX网络编程,第1卷,第3版'。
你需要做出许多决策,包括:
这些决策会极大地影响所需的代码。如果进程每次只处理一个短消息,那么考虑使用UDP而不是TCP可能是合适的。如果进程正在与多个通信者进行长时间对话,并且没有fork一个子进程来处理它们,那么可以考虑使用线程编程。如果不是,则需要考虑及时性以及中央进程是否可能无限期地被阻塞。
如评论中所示,您还需要考虑进程应该如何处理中央进程未运行的情况,以及响应速度应该有多快。您还必须防止中央进程过于繁忙,以至于看起来它没有运行,即使它正在运行但正在忙于处理其他连接。如果无法连接到中央进程的进程尝试启动新副本,会遇到多大麻烦?