Unix Socket без отправки (или получения) очереди

У меня есть пара кодов отправителя/получателя, написанная на C и Python. Клиент создает данные и отправляет их через сокет unix получателю. Получатель не всегда слушает сокет, потому что он должен что-то делать с полученными данными.

В моем текущем коде все сообщения, отправленные отправителем, ожидают в очереди получения получателем, но я не хочу такого поведения. Я хочу, чтобы отправитель знал, что получатель сейчас занят (может быть, даже путем выдачи ошибки). Итак, как я могу установить длину очереди получателя равной нулю?

Учтите, что я не хочу, чтобы процедура отправки или получения блокировалась.

Мои части кодов получателя и отправителя таковы:

Получатель (на 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

Отправитель (в С):

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

person MostafaR    schedule 05.09.2014    source источник
comment
Я приглашаю вас посмотреть, как работает man 3 select, я думаю, это может помочь вам узнать состояние приемника.   -  person CollioTV    schedule 05.09.2014
comment
@CollioTV Спасибо, я знал о select, но я думаю, что это очень общий ответ. Кстати, я читаю это.   -  person MostafaR    schedule 05.09.2014
comment
select() только говорит вам, что некоторые send() будут работать без блокировки, то, что ваши отправленные данные в конечном итоге ожидают в буфере ОС, является допустимым (и вероятным) событием после того, как select() говорит вам, что все в порядке с send()   -  person John Hascall    schedule 05.09.2014


Ответы (2)


Вы не можете сказать на стороне отправителя, что происходит на стороне получателя. Может быть, процесс приемника сейчас даже не запланирован. Единственный разумный способ - ответить от получателя обратно отправителю, где вы можете подождать некоторое время для этого ответа и решить, занят получатель или нет.

person Геннадий Казачё&    schedule 05.09.2014
comment
Большое спасибо за ваш ответ, если я хочу упростить, мне будет достаточно, если сообщения не ждут в очереди, я имею в виду, могу ли я открыть сокет в коде получателя, у которого нет очереди? Для меня нормально, если я теряю сообщения, доставленные, когда получатель занят. - person MostafaR; 05.09.2014
comment
Короче говоря - нет, нельзя. Как правило, когда вы отправляете () некоторые данные, вы просите ядро ​​​​доставить ваше сообщение в другой сокет. Именно в этот момент (предположим, что у вас есть 1 процессор, для ясности) ваш процесс приемника не работает, он ожидает планирования ядром. Ядро ДОЛЖНО хранить ваше сообщение где-то, откуда ваш получатель сможет получить его позже, когда его обработка будет запланирована. - person Геннадий Казачё&; 05.09.2014

Вам нужен какой-то способ, чтобы получатель сигнализировал о своем состоянии (прочитано или нет) отправителю. Для этой цели можно использовать несколько примитивов 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);
person John Hascall    schedule 05.09.2014