使用UNIX流套接字的IPC

时间:2014-07-10 06:52:05

标签: c sockets unix ipc

我有一个波束成形和信号处理系统,其中3个不同的独立进程可以单独启动,并且需要每隔几毫秒发送8MB的数据块。我在这些进程中使用了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()函数返回“没有这样的文件或目录”错误,我是否正确地认为发生这种情况是因为内核在我创建新内存之前没有从最后一个连接释放套接字或我错过了什么。

  4. 帮助我非常感激。感谢。

1 个答案:

答案 0 :(得分:2)

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

    • 每个插槽运行一个线程。

    • 或者您在套接字池上运行selectpoll以决定下一步该做什么。 libev等图书馆可以让您的生活更轻松。查看following example

  2. 是。客户启动时仅connect,仅在客户退出时拨打close

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