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
ошибки (обычно) не обнаруживаются во время компиляции. Файловые дескрипторы просты int
s. Компилятор не может знать, какой int
s являются действительными файловыми дескрипторами во время выполнения или, если определенная комбинация flags
допустимо для сокетов, которые вы используете, например.)
В вызове arecv() (на сервере) параметр flags не может быть равен 0:
recv(sock, buf, 14, 0)
Попробуйте что-то вроде:
recv(sock, buf, 14, MSG_WAITALL)
Смотрите страницу man для полного списка параметров параметра flags. Здесь нужно быть осторожным в отношении того, как сообщение должно быть получено.
Причина, по которой клиент не получает сообщение об ошибке (INVALID ARG), заключается в том, что он не выполняет никаких recv-операций... только сервер выполняет получение.