Сокеты BSD — использование отправки и получения

Я пытаюсь реализовать простую программу чата в Linux с использованием сокетов bsd. Сейчас я просто пытаюсь отправить и получить одно сообщение на сервер от клиента. Всякий раз, когда я запускаю код, recv возвращает -1, а код ошибки равен 22.

Код сервера -

struct sockaddr name;
char buf[80];

int main(int agrc, char** argv) {

    int sock, new_sd;   //sock is this socket, new_sd is connection socket
    int adrlen, cnt;

    name.sa_family = AF_UNIX;
    strcpy(name.sa_data, "/tmp/servsock");
    adrlen = strlen(name.sa_data) + sizeof(name.sa_family);

    sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if (sock < 0) {
        cout<<"\nserver socket failure "<<errno;
        cout<<"\nServer: ";
        exit(1);
    }

    unlink("/tmp/servsock");
    if(bind (sock, &name, adrlen) < 0)
        cout<<"\nBind failure "<<errno;

    if(listen(sock, 5) < 0)
        cout<<"\nlisten error "<<errno;

    while(1) {
        if( new_sd = accept(sock, &name, (socklen_t*)&adrlen) < 0) {
            cout<<"\nserver accept failure "<<errno;
            exit(1);
        }

        char* buf = new char[14];

        if(recv(sock, buf, 14, 0) < 0) {
            cout<<"\nError receiving data "<<errno;
            exit(1);
        }
    }   //end while
    return 0;
}

Код клиента -

struct sockaddr name;

int main(int agrc, char** argv) {

    int sock, new_sd, adrlen, cnt;
    sock = socket(AF_UNIX, SOCK_STREAM, 0);

    if (sock < 0) {
        cout<<"\nserver socket failure "<<errno;
        cout<<"\nServer: ";
        exit(1);
    }

    //stuff for server socket
    name.sa_family = AF_UNIX;
    strcpy(name.sa_data, "/tmp/servsock");
    adrlen = strlen(name.sa_data) + sizeof(name.sa_family);

    if(connect(sock, &name, adrlen) < 0) {
        cout<<"\nclient connection failure "<<errno;
        exit(1);
    }

    cout<<"\nSuccessful connection from client 1";

    std::string buf = "\nClient 1 Here";

    if(send(sock, buf.c_str(), strlen(buf.c_str()), 0) < 0) {
        cout<<"\nError sending data from client 1 "<<errno;
        exit(1);
    }
    cout<<"\nExiting normally";
    return 0;
}

Несмотря на то, что я получаю сообщение об ошибке на стороне сервера, я не получаю сообщение об ошибке на стороне клиента - оно просто нормально завершается.

Согласно - http://www.workers.com.br/manuais/53/html/tcp53/mu/mu-7.htm сообщение об ошибке errno 22 просто означает «Неверный аргумент». Но я не знаю, как именно это интерпретировать... если аргумент недействителен, зачем он вообще компилируется?

Если кто-нибудь может указать, что я делаю неправильно здесь, я был бы очень благодарен. И любые другие небольшие заметки, на которые вы хотите указать, будут приветствоваться. Спасибо за любую помощь.


person Sterling    schedule 13.07.2011    source источник
comment
не проверяйте числовое значение errno, вместо этого сравните с EINVAL или используйте %m для печати описания ошибки.   -  person littleadv    schedule 14.07.2011
comment
Попробуйте прочитать это руководство: beej.us/guide/bgnet/output/html. /singlepage/bgnet.html   -  person Vinicius Kamakura    schedule 14.07.2011


Ответы (3)


Помимо всех других проблем в вашем коде, вы пытаетесь прочитать неправильный файловый дескриптор — он должен быть new_sd, а не sock, который является серверным сокетом и может только accept() новых соединений.

Редактировать 0:

Большой бу-бу:

if( new_sd = accept(sock, &name, (socklen_t*)&adrlen) < 0) { ...

Это эквивалентно:

if( new_sd = (accept(sock, &name, (socklen_t*)&adrlen) < 0)) {

Таким образом, new_sd получает совершенно неправильное значение. Общая мудрость заключается в том, чтобы не помещать задания в условные операторы. Рассмотрите возможность компиляции с высоким уровнем предупреждений, по крайней мере, -Wall -pedantic.

person Nikolai Fetissov    schedule 13.07.2011
comment
Я изменил это, и я все еще получаю сообщение об ошибке, но теперь это Cross Mount Point (88). Что это значит? - person Sterling; 14.07.2011
comment
Хорошо, если принять этот вызов из условного оператора, он будет работать нормально. Спасибо! - person Sterling; 14.07.2011

Одна вещь, которая выглядит неправильно в вашем коде, заключается в том, что вы recv работаете с sock, когда вы должны recv работать с new_fd. Не знаю, почему это даст EINVAL.

(Ошибки EINVAL (обычно) не обнаруживаются во время компиляции. Файловые дескрипторы представляют собой простые ints. Компилятор не может знать, какие int являются допустимыми файловыми дескрипторами во время выполнения, или допустима ли определенная комбинация flags для сокетов, которые вы используете, например .)

person Mat    schedule 13.07.2011

В вызове recv() (на сервере) параметр flags не может быть равен 0:

recv(sock, buf, 14, 0)

Попробуйте что-то вроде:

recv(sock, buf, 14, MSG_WAITALL)

См. страницу «man» для полного списка опций для параметра «flags». Здесь нужно быть рассудительным в отношении того, как сообщение должно быть получено.

Причина, по которой клиент не получает сообщение об ошибке (INVALID ARG), заключается в том, что он не выполняет никаких приемов... только сервер выполняет прием.

person Sally Recuas    schedule 26.08.2011
comment
Я боюсь, что вы ошибаетесь в отношении флагов, действительно можно передать ноль для флагов, если вы вообще не хотите никаких флагов. - person Some programmer dude; 18.11.2011