使用 Unix 域套接字进行电话对话的 IPC 机制
Posted
技术标签:
【中文标题】使用 Unix 域套接字进行电话对话的 IPC 机制【英文标题】:IPC mechanism for telephone conversation using Unix domain sockets 【发布时间】:2014-03-18 21:09:10 【问题描述】:我正在为电话对话实现 IPC。创建了两个文件:receiver.c 和 caller.c.. rc.h 包含所有包含文件。我正在根据 FIFO 的 .. 测试 Unix 域套接字的使用。 caller.c 文件是:
#include "rc.h"
int main()
int sock_fd;
struct sockaddr_un unix_addr;
char buf[2048];
int n;
if ((sock_fd=socket(AF_UNIX,SOCK_STREAM,0))<0)
perror("cli:socket()");
exit(1);
unix_addr.sun_family=AF_UNIX;
strcpy(unix_addr.sun_path,SERVER);
if (connect(sock_fd,(struct sockaddr *) &unix_addr,
sizeof(unix_addr.sun_family)+
sizeof(unix_addr.sun_path))< 0)
perror("cli:connect()");
exit(1);
sprintf(buf,"Reciever called by receiver");
n=strlen(buf)+1;
if (write (sock_fd,buf,n)!=n)
perror("cli:write()");
exit(1);
printf("Caller sent-->%s",buf);
if ((n=read(sock_fd,buf,2047))<0)
perror("cli:read()");
exit(1);
buf[n]=0;
while (buf[n]==0)n--;
if (buf[n]=='\n')
buf[n]='\0';
printf("Reciever received<--%s \n",buf);
exit(0);
receiver.c 是:
#include <signal.h>
#include "rc.h"
static void stop(int n)
unlink(SERVER);
exit(0);
static void receiver()
int sock_fd,cli_sock_fd;
struct sockaddr_un unix_addr;
char buf[2048];
int n,addr_len;
pid_t pid;
char *pc;
signal(SIGINT,stop);
signal(SIGQUIT,stop);
signal(SIGTERM,stop);
unix_addr.sun_family=AF_UNIX;
strcpy(unix_addr.sun_path,SERVER);
addr_len=sizeof(unix_addr.sun_family)+strlen(unix_addr.sun_path);
unlink(SERVER);
if (bind(sock_fd,(struct sockaddr *)&unix_addr,addr_len)<0)
perror("Receiver:bind()");
exit(1);
if (listen(sock_fd,5)<0)
perror("Receiver:caller()");
unlink(SERVER);
exit(1);
while ((cli_sock_fd=accept(sock_fd,(struct sockaddr*)&unix_addr,&addr_len))>=0)
if ((n=read(cli_sock_fd,buf,2047))<0)
perror("Receiver:read()");
close(cli_sock_fd);
continue;
buf[n]='\0';
for(pc=buf;*pc!='\0' && (*pc<'0' || *pc>'9');pc++);
pid=atol(pc);
if (pid!=0)
sprintf(buf,"Receiver called by caller\n",pid);
n=strlen(buf)+1;
if (write(cli_sock_fd,buf,n)!=n)
perror("Receiver:write()");
close(cli_sock_fd);
perror("Receiver:accept()");
unlink(SERVER);
exit(1);
int main()
int r;
if ((r=fork())==0)
receiver();
if(r<0)
perror("Receiver:fork()");
exit(1);
exit(0);
现在在编译时出现问题:
sourajyoti@ubuntu:~/os2$ gcc receiver.c -o test1
receiver.c: In function ‘stop’:
receiver.c:6:9: warning: unknown escape sequence: '\s' [enabled by default]
receiver.c: In function ‘receiver’:
receiver.c:23:28: warning: unknown escape sequence: '\s' [enabled by default]
receiver.c:25:9: warning: unknown escape sequence: '\s' [enabled by default]
receiver.c:34:10: warning: unknown escape sequence: '\s' [enabled by default]
receiver.c:58:9: warning: unknown escape sequence: '\s' [enabled by default]
然后在这之后:
sourajyoti@ubuntu:~/os2$ ./test1
Receiver:bind(): Bad file descriptor
客户端也一样:
sourajyoti@ubuntu:~/os2$ gcc caller.c -o test2
caller.c: In function ‘main’:
caller.c:15:28: warning: unknown escape sequence: '\s' [enabled by default]
sourajyoti@ubuntu:~/os2$ ./test2
cli:connect(): No such file or directory
头文件rc.h为:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#define SERVER "\tmp\server"
【问题讨论】:
pat 回答了你,但我有一个很好的使用 /temp 的解决方案,使用mktemp function
。 man 3 mktemp
你能详细说明一下吗?我是新手..
\s 我已经设法改变了。但是绑定仍然是一个问题。我不明白为什么套接字无法创建??
你把SERVER
改成了什么?您是否在接收器中添加了对socket()
的呼叫?
【参考方案1】:
我已经说过,pat 回答了你,但我说的是使用mktemp
:
char sfn[15] = "";
FILE *sfp;
strlcpy(sfn, "/tmp/ed.XXXXXX", sizeof sfn);
if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL)
fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
return (NULL);
return (sfp);
应该这样改写:
char sfn[15] = "";
FILE *sfp;
int fd = -1;
strlcpy(sfn, "/tmp/ed.XXXXXX", sizeof sfn);
if ((fd = mkstemp(sfn)) == -1 ||
(sfp = fdopen(fd, "w+")) == NULL)
if (fd != -1)
unlink(sfn);
close(fd);
fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
return (NULL);
return (sfp);
【讨论】:
目标是创建一个客户端和服务器都知道的名称的 UNIX 域套接字。此代码创建一个文件,其名称只有该程序知道。 pat,我之前说过,我只是想帮助如何使用/temp
,如果你想使用write socket daemon,请将socket与daemon分开。谷歌如何编写守护进程,我建议:netzmafia.de/skripten/unix/linux-daemon-howto.html,并阅读更多关于 TCP 或 UDP 的信息,因为我不了解你的项目,有些项目需要 UDP,有些需要 TCP。
为您的套接字用户 POSIX therad ,命名为 ptherad
【参考方案2】:
您的 SERVER
宏具有非法的 '\s'
转义序列。不幸的是,您没有显示标题的内容,所以我看不到定义。
您的接收器实际上并没有创建套接字。它只是绑定了一个未初始化的sock_fd
,导致它失败。
客户端失败,因为接收方从未创建过它可以连接的套接字。
编辑
好的,现在我可以看到SERVER
的定义,我看到您在路径名中使用了反斜杠而不是正斜杠。
在receiver中,你还需要创建一个socket,代码和client类似:
if ((sock_fd=socket(AF_UNIX,SOCK_STREAM,0))<0)
perror("Receiver:socket()");
exit(1);
通常,当我bind
一个UNIX域套接字时,我只是给sizeof(unix_addr)
作为地址长度:
if (bind(sock_fd,(struct sockaddr *)&unix_addr,sizeof(unix_addr))<0)
perror("Receiver:bind()");
exit(1);
【讨论】:
我已经上传了rc.h文件。 \s 我已经设法改变了。但是绑定仍然是一个问题。我不明白为什么套接字无法创建??以上是关于使用 Unix 域套接字进行电话对话的 IPC 机制的主要内容,如果未能解决你的问题,请参考以下文章