【问题标题】:IPC using UNIX stream sockets使用 UNIX 流套接字的 IPC
【发布时间】:2014-08-31 10:53:17
【问题描述】:

我有一个波束成形和信号处理系统,其中可以分别启动 3 个不同的独立进程,并且需要每隔几毫秒相互发送 8MB 的数据块。我在这些进程中为 IPC 使用了 UNIX 流套接字。我将块的接收者作为套接字服务器,将发送者作为客户端。每次发送方有数据要发送时,它都会连接到服务器,将数据放在套接字上并断开连接。这完美地工作,但是由于发送者以非常高的频率发送数据,我从套接字的“connect()”函数中得到很多错误,如“没有这样的文件或目录”。我猜这是因为套接字尚未从上次传输中释放出来。

客户端功能:

int sockDAQ, len,respServer;
struct sockaddr_un remote;
int dispConStatus;



        for( j=0;j<16;j++){    

        if ((sockDAQ = socket(AF_UNIX,SOCK_STREAM, 0)) == -1) 
            perror("socket");
        remote.sun_family = AF_UNIX;
        switch(*(daqNum))
        {
            case DAQ1 : strcpy(remote.sun_path, SOCKET_DAQ1_PATH);
                        break;
            case DAQ2 : strcpy(remote.sun_path, SOCKET_DAQ2_PATH);
                        break;
            case DAQ3 : strcpy(remote.sun_path, SOCKET_DAQ3_PATH);
                        break;
            case DAQ4 : strcpy(remote.sun_path, SOCKET_DAQ4_PATH);
                        break;
            case DAQ5 : strcpy(remote.sun_path, SOCKET_DAQ5_PATH);
                        break;
            case DAQ6 : strcpy(remote.sun_path, SOCKET_DAQ6_PATH);
                        break;
            case DAQ7 : strcpy(remote.sun_path, SOCKET_DAQ7_PATH);
                        break;
            case DAQ8 : strcpy(remote.sun_path, SOCKET_DAQ8_PATH);
                        break;

        } 

len = strlen(remote.sun_path) + sizeof(remote.sun_family);    
dispConStatus = connect(sockDAQ, (struct sockaddr *)&remote, len);
        if ( dispConStatus != -1) {
            //printf("beamformer process found by %d.. Transferring packet\n",*(daqNum));     
            //printf("j : %d\n", j);
            respServer = NOT_TERMINATE;
            if ((send(sockDAQ, &respServer, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, &transfer_bytes, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, buf_1, transfer_bytes, 0))==-1) perror("send");
            pthread_mutex_lock(&bfmutex);
            printf("PACKETS TRANSFERRED %d FROM DAQ %d\n",++sentCount,*(daqNum));
            pthread_mutex_unlock(&bfmutex);

            }
        else
            printf("FAILED TO FIND BF FOR DAQ %d\n",*(daqNum));

        }

如果我尝试类似的方法,我连接到服务器一次,然后继续发送数据包,第一次传输后它似乎不起作用,因为“connect()”函数每次都返回 -1。

更新功能:

int sockDAQ, len,respServer;
struct sockaddr_un remote;
int dispConStatus;

if ((sockDAQ = socket(AF_UNIX,SOCK_STREAM, 0)) == -1) 
            perror("socket");
remote.sun_family = AF_UNIX;
        switch(*(daqNum))
        {
            case DAQ1 : strcpy(remote.sun_path, SOCKET_DAQ1_PATH);
                        break;
            case DAQ2 : strcpy(remote.sun_path, SOCKET_DAQ2_PATH);
                        break;
            case DAQ3 : strcpy(remote.sun_path, SOCKET_DAQ3_PATH);
                        break;
            case DAQ4 : strcpy(remote.sun_path, SOCKET_DAQ4_PATH);
                        break;
            case DAQ5 : strcpy(remote.sun_path, SOCKET_DAQ5_PATH);
                        break;
            case DAQ6 : strcpy(remote.sun_path, SOCKET_DAQ6_PATH);
                        break;
            case DAQ7 : strcpy(remote.sun_path, SOCKET_DAQ7_PATH);
                        break;
            case DAQ8 : strcpy(remote.sun_path, SOCKET_DAQ8_PATH);
                        break;

        } 

len = strlen(remote.sun_path) + sizeof(remote.sun_family);    
dispConStatus = connect(sockDAQ, (struct sockaddr *)&remote, len);



        if ( dispConStatus != -1) {

            respServer = NOT_TERMINATE;
            if ((send(sockDAQ, &respServer, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, &transfer_bytes, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, buf_1, transfer_bytes, 0))==-1) perror("send");

            pthread_mutex_lock(&bfmutex);
            printf("PACKETS TRANSFERRED %d FROM DAQ %d\n",++sentCount,*(daqNum));
            pthread_mutex_unlock(&bfmutex);

            usleep(5000);

            respServer = NOT_TERMINATE;
            if ((send(sockDAQ, &respServer, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, &transfer_bytes, sizeof(int), 0))==-1) perror("send");
            if ((send(sockDAQ, buf_1, transfer_bytes, 0))==-1) perror("send");

            pthread_mutex_lock(&bfmutex);
            printf("PACKETS TRANSFERRED %d FROM DAQ %d\n",++sentCount,*(daqNum));
            pthread_mutex_unlock(&bfmutex);

            }

        close(sockDAQ);

这会在 send() 函数上返回错误:

../sysdeps/unix/sysv/linux/x86_64/send.c: No such file or directory.

我的问题是:

  1. 每次需要向套接字发送数据包时,是否需要终止连接并重新连接。

  2. 有没有办法无限期地维护套接字连接,因为持续的连接和重新连接会在我的系统中造成大量延迟,并且我正在通过套接字丢弃数据包。

  3. 关于 connect() 函数返回“没有这样的文件或目录”错误,我是否正确地假设发生这种情况是因为在我建立新连接之前内核没有从最后一个连接中释放套接字,或者我错过了什么吗?

非常感谢您的帮助。谢谢。

【问题讨论】:

  • 您应该保持连接打开。所以在程序开始时打开它,只在程序结束时关闭它。
  • 第二个代码做同样的事情,它打开连接并发送 2 个数据包,然后关闭连接,但是它不起作用,因为第二个数据包不出去,我得到错误:../ sysdeps/unix/sysv/linux/x86_64/send.c:没有这样的文件或目录。

标签: c sockets unix ipc


【解决方案1】:
  1. 不,你不需要关闭套接字,你可以保持它打开。请注意,这可能会显着改变服务器的逻辑。您将需要维护一个套接字池,其中包括侦听套接字和每个客户端一个套接字。那么你有两种架构选择:

    • 要么每个套接字运行一个线程。

    • 或者你在套接字池上运行selectpoll 来决定下一步做什么。 libev 之类的库可能会让您的生活更轻松。查看following example

  2. 是的。仅在您的客户端启动时调用connect,仅在您的客户端退出时调用close

  3. 我认为发生此错误是因为您需要保持accept-ing 连接。根据您对服务器的编程方式,它可能正忙于处理不同的客户端,而不是接受新的连接。查看this example,了解如何接受多个连接。

【讨论】:

    猜你喜欢
    • 2014-07-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多