【问题标题】:Unix Socket without sending (or receiving) queue没有发送(或接收)队列的 Unix Socket
【发布时间】:2014-10-30 05:25:39
【问题描述】:

我有一对用 C 和 Python 编写的发送方/接收方代码。客户端正在生成数据并通过 unix 套接字将其发送到接收器。 Receiver 并不总是在监听套接字,因为它应该对接收到的数据做一些事情。

在我当前的代码中,发送方发送的所有消息都在队列中等待接收方接收,但我不希望这种行为。我希望发送者知道接收者现在很忙(甚至可能通过引发错误)。那么如何将接收者的队列长度设置为零呢?

请考虑我不希望发送或接收过程被阻塞。

我的接收方和发送方代码部分如下:

接收器(在 Python 中):

self.app_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
self.app_socket.settimeout(0.01)
self.app_socket.bind(APP_SOCKET)

def poll(self, *args):
    try:
        message = self.app_socket.recv(1024)
    except socket.timeout:
        return

发件人(在 C 中):

int openSocket(char *path)
{
    int sock;
    struct sockaddr_un addr;
    int size;

    sock = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sock < 0)
        exit (EXIT_FAILURE);

    addr.sun_family = AF_UNIX;
    strcpy(addr.sun_path, path);
    size = strlen(addr.sun_path) + sizeof(addr.sun_family);

    if (connect(sock, (struct sockaddr *) &addr, size) < 0)
        return -1;

    return sock;
}

int sendMessage(int sock, unsigned char *message, int length)
{
    int count;

    count = send(sock, message, length, 0);
    if (count < 0)
        return -1;

    return count;
}

【问题讨论】:

  • 我邀请您看看man 3 select是如何工作的,我认为它可以帮助您了解接收器的状态
  • @CollioTV 谢谢,我知道select,但我认为这是一个非常笼统的答案。顺便说一句,我正在读这篇文章。
  • select() 仅告诉您某些send() 是否可以在没有阻塞的情况下工作,在select() 告诉您之后,让您发送的数据最终在操作系统缓冲区中等待是有效的(并且可能)发生可以send()

标签: python c sockets unix-socket


【解决方案1】:

您无法在发送方告诉接收方发生了什么。可能现在甚至没有安排接收进程。唯一合理的方法是从接收方回复给发送方,您可以在此等待一些超时时间来决定接收方是否忙。

【讨论】:

  • 非常感谢您的回答,如果我想让它更容易,如果消息不在队列中等待就足够了,我的意思是我可以在接收器代码中打开一个套接字没有排队吗?如果我在收件人忙时丢失了传递的消息,对我来说没关系。
  • 简而言之 - 不,你不能。通常,当您 send() 一些数据时,您要求内核将您的消息传递到另一个套接字。就在那一刻(为了清楚起见,假设您有 1 个 cpu)您的接收器 proc 不工作,它正在等待内核调度。内核必须将您的消息存储在某个地方,以便您的接收者稍后可以得到它,当它的 proc 将被安排时。
【解决方案2】:

您需要某种方式让接收方将其状态(读取或未读取)发送给发送方。 有几个 IPC 原语可以用于此目的。

或者你可以自己编。 例如,接收者可以这样:

    mkdir("/path/to/my/flag/dir", 0555);  /* ready */
    read();
    rmdir("/path/to/my/flag/dir");       /* busy */

并且发件人可以通过以下方式定期检查是否存在此内容:

    oktogo = (access("/path/to/my/flag/dir", F_OK) == 0);

【讨论】:

    猜你喜欢
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    相关资源
    最近更新 更多