【问题标题】:Is there any extra parameters or settings need to be done to get unix socket connection through poll fd in C, linux?是否需要做任何额外的参数或设置才能通过 C、linux 中的 poll fd 获得 unix 套接字连接?
【发布时间】:2017-10-12 06:14:59
【问题描述】:

我有一个 Unix 域套接字服务器。在我的服务器应用程序中,我创建了一个线程。在这个线程中,我创建了一个 unix 服务器套接字。另外,我创建了一个 poll fd 来检查套接字上的任何活动。因此,套接字上可以有两个活动 - 首先是连接接受,一旦连接被接受,我需要监视该连接。在我的示例中,我假设只有 1 个套接字客户端。我的问题是,当客户端应用程序尝试连接时,我从未在套接字上获得连接事件。但是,我的客户端应用程序说已连接。这是我的服务器程序和客户端程序。我在这里想念什么?我很困惑。是否有任何额外的设置/参数要做。 不过我觉得逻辑是对的。

服务器应用

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

这一切都在嵌入式应用程序中运行,所以我没有太多的套接字实用程序来检查我忙碌的盒子。

【问题讨论】:

    标签: c linux sockets unix


    【解决方案1】:

    我尝试了你的代码,它对我来说很好(在 Debian 9.1 上测试)。

    我怀疑这是由带有没有终止 \n 字符的字符串的 printf() 引起的。默认情况下,tty/pty 上的printf() 到标准输出是行缓冲的,直到\n 或缓冲区已满,您才会看到结果。因此,首先您可以尝试将\n 添加到您的 printf 字符串中。

    【讨论】:

    • 关于 unix sock 路径不匹配,这是堆栈溢出中的复制粘贴错误。对不起。接下来,我有 syslog 而不是 printf。 \n 在系统日志中也很重要吗?
    • \n 能解决您的问题吗? Syslog 应该可以很好地处理非 \n 终止的消息。
    • 它没有解决我的问题。
    • 你能在if (events &gt; 0) 块中printf("%#x %#x\n", fds[0].revents, POLLIN) 吗?
    • 一直 - 0 0x1
    【解决方案2】:

    我同意 pynexj。尝试添加'\n'

    你的代码有错误,服务器和客户端的socket路径文件名应该相同,域socket只能用于本地通信(客户端和服务器应该在一台机器和操作系统中)。

    调试这种简单的问题,我发现你的客户端可以正确连接到服务器,并且服务器显示它得到了一些事件。(当服务器打印“...accept itGot some event...”)。

    我在ubuntu 16.04 LTS上运行你的代码,它很容易兼容大多数Linux发行版。如果你发现嵌入式系统很难调试,你可以先在你的X86_64电脑上调试它们,而不用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
    

    【讨论】:

    • 抱歉,发布问题时unix域套接字路径名有问题。
    猜你喜欢
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多