2017-10-12 41 views
0

我有一个Unix域套接字服务器。在我的服务器应用程序中,我创建了一个线程。在这个线程中,我创建了一个unix服务器套接字。另外,我创建了一个轮询fd来检查套接字上的任何活动。所以,在套接字上可以有两个活动 - 第一个是连接接受,一旦连接被接受,我需要监视该连接。在我的例子中,我假设只有一个套接字客户端。我的问题是,当客户端应用程序尝试连接时,我从来没有在连接的套接字上获得事件。但是,我的客户端应用程序说连接。这是我的服务器程序和客户端程序。我在这里错过了什么?我感到困惑。是否有任何额外的设置/参数要做。 虽然我觉得逻辑是正确的。是否有任何额外的参数或设置需要通过在C,Linux中通过轮询fd来获取unix套接字连接?

服务器应用

#define WEBSOCK_PATH_NAME "/tmp/websock" 
int createServerSocket(void) 
{ 
    struct sockaddr_un saddr; 
    char buf[128]; 
    int sock = socket(AF_UNIX, SOCK_STREAM, 0); 
    if (sock < 0) 
    { 
     printf("failed to create UN socket, errno=%d\n", errno); 
     return -1; 
    } 
    memset(&saddr, 0, sizeof(saddr)); 
    saddr.sun_family = AF_UNIX; 
    strncpy(saddr.sun_path, WEBSOCK_PATH_NAME, sizeof(saddr.sun_path)); 
    if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { 
     strerror_r(errno, buf, sizeof(buf)); 
     printf("failed to bind address %s errno=%d: %s\n", 
       WEBSOCK_PATH_NAME, errno, buf); 
     close(sock); 
     return -1; 
    } 
    if (listen(sock, 2) != 0) { 
     strerror_r(errno, buf, sizeof(buf)); 
     printf("listen failed for %s errno=%d: %s\n", 
       WEBSOCK_PATH_NAME, errno, buf); 
     close(sock); 
     perror("listen failed: "); 
     return -1; 
    } 
    printf("Created WebIntStat Server\n"); 
    return sock; 
} 

void Thread() 
    { 
     int websock; 
     struct pollfd fds[2]; 
     nfds_t numfds; 

     websock = CreateServerSocket(); 

     if(websock == -1) 
     { 
      printf("Failed in creating socket"); 
      return; 
     } 

     // make it usable by everyone 
     memset(fds, 0, sizeof(fds)); 
     chmod(WEBSOCK_PATH_NAME, 0777); 
     numfds = 1; // presently monitor 1 fd 
     fds[0].fd = webSock; 
     fds[0].events = POLLIN; 
     fds[0].revents = 0; 

     while(1) 
     { 
      // Want to run this and check the data every 1 second to do other stuffs 
      int events = poll(fds, numfds, 1000); 
      if(events > 0) 
      { 
       // I get this print 
       printf("Got some events"); 
       if (fds[0].revents & POLLIN) 
       { 
         // I never get this one ------ 
         printf("Got Connection Request..accept it"); 

         //socket accept code. 

       } 
      } 

     } 

    } 

客户端代码

#define SOCKET_PATH "/tmp/websock" 
int main() 

    { 
     int sockfd; 
     int len; 
     struct sockaddr_un address; 
     int result; 
     char ch[5] = "Start"; 


     /* -AF_UNIX is a UNIX internal socket, created on the filesystem. 
     * -SOCK_STREAM is a reliable, sequenced, connection-based two-way byte stream 
     * (INET equivalent is TCP) */ 

     sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 


     /* -sun_family - specifies type (domain) of socket 
     * -sun_path - socket path location (on filesystem) */ 
     address.sun_family = AF_UNIX; 
     strcpy(address.sun_path, SOCKET_PATH); 
     len = sizeof(address); 


     /* request connection from the server, connecting socket to server with specified address 
     * 'len' is the length of the address */ 
     result = connect(sockfd, (struct sockaddr *)&address, len); 


     /* exit with error if connection is not successful */ 
     if(result == -1) { 
      perror("oops: client1"); 
      exit(1); 
     } 

     printf("Connected"); 
     /* otherwise write data to server and obtain response */ 
     write(sockfd, ch, 5); 
     read(sockfd, &ch, 5); 
     printf("char from server: %s\n", ch); 
     close(sockfd); 

     exit(0); 
    } 

这是所有嵌入式应用程序中运行,所以我没有太多的插座工具来检查我的忙箱。

回答

0

我同意pynexj。尝试添加“\ n”

出现在你的代码中的一些错误,插座路径文件名应该是在服务器和客户端一样,和域套接字只能在本地通信使用(客户端和服务器在一台机器应该和OS)。我们发现你的客户端可以正确地连接到服务器,并且服务器显示它得到一些事件(因为服务器打印“...接受它有一些事件...”)。

我在ubuntu 16.04 LTS中运行你的代码,它将很容易在大多数Linux发行版中兼容。如果你发现嵌入式系统很难调试,你可以先在你的X86_64 PC上调试它们,而不使用arm编译器,代码来武装。

也许你把你的客户端和服务器在不同的机器,以及客户端打开一个本地存在的文件(但实际上没有服务器一边收听),

也许有您的服务器的IO或线程一些问题。

serv.c

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 
#include <sys/types.h>   /* See NOTES */ 
#include <sys/socket.h> 
#include <errno.h> 
#include <sys/stat.h> 
#include <poll.h> 
#include <sys/un.h> 
int poll(struct pollfd *fds, nfds_t nfds, int timeout); 
#define _GNU_SOURCE   /* See feature_test_macros(7) */ 
#include <signal.h> 
#include <poll.h> 
#define WEBSOCK_PATH_NAME "/tmp/websock" 
int createServerSocket(void) 
{ 
    struct sockaddr_un saddr; 
    char buf[128]; 
    int sock = socket(AF_UNIX, SOCK_STREAM, 0); 
    if (sock < 0) 
    { 
     printf("failed to create UN socket, errno=%d\n", errno); 
     return -1; 
    } 
    memset(&saddr, 0, sizeof(saddr)); 
    saddr.sun_family = AF_UNIX; 
    strncpy(saddr.sun_path, WEBSOCK_PATH_NAME, sizeof(saddr.sun_path)); 
    if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { 
     strerror_r(errno, buf, sizeof(buf)); 
     printf("failed to bind address %s errno=%d: %s\n", 
       WEBSOCK_PATH_NAME, errno, buf); 
     close(sock); 
     return -1; 
    } 
    if (listen(sock, 2) != 0) { 
     strerror_r(errno, buf, sizeof(buf)); 
     printf("listen failed for %s errno=%d: %s\n", 
       WEBSOCK_PATH_NAME, errno, buf); 
     close(sock); 
     perror("listen failed: "); 
     return -1; 
    } 
    printf("Created WebIntStat Server\n"); 
    return sock; 
} 

void main() 
{ 
    int websock; 
    struct pollfd fds[2]; 
    nfds_t numfds; 

    websock = createServerSocket(); 

    if(websock == -1) 
    { 
     printf("Failed in creating socket"); 
     return; 
    } 

    // make it usable by everyone 
    memset(fds, 0, sizeof(fds)); 
    chmod(WEBSOCK_PATH_NAME, 0777); 
    numfds = 1; // presently monitor 1 fd 
    fds[0].fd = websock; 
    fds[0].events = POLLIN; 
    fds[0].revents = 0; 

    while(1) 
    { 
     // Want to run this and check the data every 1 second to do other stuffs 
     int events = poll(fds, numfds, 1000); 
     if(events > 0) 
     { 
      // I get this print 
      printf("Got some events"); 
      if (fds[0].revents & POLLIN) 
      { 
       // I never get this one ------ 
       printf("Got Connection Request..accept it"); 

       //socket accept code. 

      } 
     } 

    } 

} 

cli.c

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 
#include <sys/types.h>   /* See NOTES */ 
#include <sys/socket.h> 
#include <errno.h> 
#include <sys/stat.h> 
#include <poll.h> 
#include <sys/un.h> 
#define SOCKET_PATH "/tmp/websock" 
//#define WEBSOCK_PATH_NAME "/tmp/websock" 
int main() 
{ 
    int sockfd; 
    int len; 
    struct sockaddr_un address; 
    int result; 
    char ch[5] = "Start"; 


    /* -AF_UNIX is a UNIX internal socket, created on the filesystem. 
    * -SOCK_STREAM is a reliable, sequenced, connection-based two-way byte stream 
    * (INET equivalent is TCP) */ 

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 


    /* -sun_family - specifies type (domain) of socket 
    * -sun_path - socket path location (on filesystem) */ 
    address.sun_family = AF_UNIX; 
    strcpy(address.sun_path, SOCKET_PATH); 
    len = sizeof(address); 


    /* request connection from the server, connecting socket to server with specified address 
    * 'len' is the length of the address */ 
    result = connect(sockfd, (struct sockaddr *)&address, len); 


    /* exit with error if connection is not successful */ 
    if(result == -1) { 
     perror("oops: client1"); 
     exit(1); 
    } 

    printf("Connected"); 
    /* otherwise write data to server and obtain response */ 
    write(sockfd, ch, 5); 
    read(sockfd, &ch, 5); 
    printf("char from server: %s\n", ch); 
    close(sockfd); 

    exit(0); 
} 

你可以用下面的命令编译它们:

gcc serv.c -o serv 
gcc cli.c -o cli 

干净套接字文件,如果它已经在使用:

rm -rf /tmp/websock 

然后运行它们:

./serv 
./cli 

服务器端输出:

Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..ac 
cept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..a 
ccept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request.. 
accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request. 
.accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request 
..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Reques 
t..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Reque 
st..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Requ 
est..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Req 
uest..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Re 
quest..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection R 
equest..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection 
Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection 
Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connectio 
n Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connecti 
on Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connect 
ion Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connec 
tion Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Conne 
ction Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Conn 
ection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Con 
nection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Connection Request..accept itGot some eventsGot Co 
nnection Request..accept itGot some eventsGot Connection Request..accept itGot some events 
+0

对不起,在发布问题时,unix域套接字路径名是个问题。 –

2

我想你的代码,并为我(在Debian 9.1测试)工作正常。

我怀疑这是由printf()造成的,而字符串没有终止\n char。默认情况下,printf()在tty/pty上的stdout被缓存,并且直到\n或缓冲区已满时才会看到结果。所以首先你可以尝试添加\n到你的printf字符串。

+0

关于unix sock path mismatch,这是堆栈溢出中的复制粘贴错误。抱歉。接下来,我有syslog而不是printf。 \ n在系统日志中是否也有问题? –

+0

确实解决了你的问题?系统日志应该可以正常使用非'n''终止的消息。 – pynexj

+0

它没有解决我的问题。 –

相关问题