BSD Sockets - Использование send и recv - PullRequest
2 голосов
/ 14 июля 2011

Я пытаюсь реализовать простую программу чата в 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 ]

5 голосов
/ 14 июля 2011

Помимо всех других проблем в вашем коде, вы пытаетесь прочитать неправильный дескриптор файла - он должен быть 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.

2 голосов
/ 14 июля 2011

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

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

0 голосов
/ 27 августа 2011

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

recv(sock, buf, 14, 0)

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

recv(sock, buf, 14, MSG_WAITALL)

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

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

...