BSD Sockets - Использование send и recv

Я пытаюсь реализовать простую программу чата в 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 просто означает "Неверный аргумент". Но я не знаю, как именно это интерпретировать... если аргумент был недействительным, зачем его вообще компилировать?

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

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,

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

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

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

recv(sock, buf, 14, 0)

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

recv(sock, buf, 14, MSG_WAITALL)

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

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

Другие вопросы по тегам