2014-03-18 34 views
0

我正在爲電話對話實現IPC。創建兩個文件:receiver.c和caller.c .. rc.h包含所有包含文件。我正在測試採用按先進先出的Unix域套接字的.. 的caller.c文件是:使用Unix域套接字進行電話對話的IPC機制

#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); 
} 

現在在編譯時我在哪裏獲得出現問題:

[email protected]:~/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] 

然後在此之後:

[email protected]:~/os2$ ./test1 
Receiver:bind(): Bad file descriptor 

同一客戶端:

[email protected]:~/os2$ gcc caller.c -o test2  
caller.c: In function ‘main’:  
caller.c:15:28: warning: unknown escape sequence: '\s' [enabled by default]  
[email protected]:~/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" 
+1

拍拍回答你,但我有使用/ TEMP一個很好的解決方案,使用'mktemp的function'。 'man 3 mktemp' – PersianGulf

+0

你能否詳細說明一下嗎?我是新手。 – Paku

+0

\我已經設法改變了..但綁定仍然是一個問題。我不明白爲什麼套接字無法創建? – Paku

回答

0

SERVER宏有一個非法'\s'轉義序列。不幸的是,你不顯示你的頭文件的內容,所以我看不到定義。

您的接收器實際上並沒有創建套接字。它只是綁定一個未初始化的sock_fd,這導致它失敗。

客戶端失敗,因爲接收方從未創建可連接的套接字。

編輯

好了,現在我可以看到SERVER的定義,我看到你正在使用反斜槓代替正的在你的路徑名斜槓。

在接收端,你還需要創建一個插座,用類似於客戶端代碼:

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); 
} 
+0

我已經上傳了rc.h文件。 – Paku

+0

\我已經設法改變..但綁定仍然是一個問題。我無法理解爲什麼套接字未能創建? – Paku

+0

是的,我看到了我的錯誤。謝謝! – Paku

0

已經我說,拍拍回答你,但我在說關於使用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); 
+0

目標是使用客戶端和服務器都知道的名稱創建UNIX域套接字。此代碼創建一個名稱僅爲此程序所知的文件。 – pat

+0

pat,我以前說過,我只想幫助'/ temp',如果你想使用寫入套接字守護進程,請將套接字從守護進程中分離出來。谷歌如何編寫守護進程,我建議:http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html,並閱讀更多關於TCP或UDP,因爲我不知道你的項目,一些項目需要UDP,一些需要TCP。 – PersianGulf

+0

爲您的套接字用戶POSIX therad,名爲'ptherad' – PersianGulf