recvfrom: неверный адрес, sendto: семейство адресов не поддерживается протоколом

Я пытаюсь реализовать небольшое UDP-серверное/клиентское приложение на C и получил две ошибки на стороне сервера: recvfrom: Bad address && sendto: семейство адресов не поддерживается протоколом. Я искал ошибку и гуглил ответы, но, к сожалению, они не очень помогли... может быть, я неправильно задаю параметр и не понимаю. Я надеюсь, что вы можете дать мне подсказку :).

#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <errno.h>

#define BUFFSIZE 256
#define IP "127.0.0.1"
#define PORT 7755

int main(void){

  int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  char buffer[1] = "s";

  struct sockaddr_in src_addr;
  struct sockaddr_in dest_addr;

  src_addr.sin_family = AF_INET;
  src_addr.sin_port = htons(PORT);
  src_addr.sin_addr.s_addr = inet_addr(IP);

  if(socket_fd==-1)
    perror("socket");

  if(bind(socket_fd, (struct sockaddr*)&src_addr, sizeof(src_addr))==-1)
    perror("bind");

  if(recvfrom(socket_fd, buffer, 2, 0, (struct sockaddr*)&dest_addr, (unsigned int *)sizeof(struct sockaddr_in))==-1)
    perror("recvfrom");

  if(sendto(socket_fd, buffer, 2, 0,(struct sockaddr*)&dest_addr, sizeof(dest_addr))==-1)
    perror("sendto");

  if(close(socket_fd)==-1)
    perror("close");

  return 0;

}

person leiseliesel    schedule 16.12.2012    source источник


Ответы (2)


Вам нужно передать действительный указатель на recvfrom. (unsigned int *)sizeof(struct sockaddr_in) не является допустимым указателем.

Изменять

 if(recvfrom(socket_fd, buffer, 2, 0, (struct sockaddr*)&dest_addr, 
             (unsigned int *)sizeof(struct sockaddr_in) == -1)

to e.g.

 socklen_t len = sizeof dest_addr;
 if(recvfrom(socket_fd, buffer, 2, 0, 
             (struct sockaddr*)&dest_addr, &len) == -1)

Вы также создаете недопустимый массив, который вы отправляете. Ваш массив имеет длину 1, но вы сообщаете sendto/recvfrom, что он имеет длину 2. Поэтому измените

char buffer[1] = "s";

to

char buffer[] = "s";

(Строка «s» — это символ «s» и нулевой байт, поэтому buffer в последнем случае будет иметь длину 2.)

person nos    schedule 16.12.2012

Цитата из Fedora 18 Beta recv/recvmsg/recv с главной страницы:

ssize_t recv(int sockfd, void *buf, size_t len, int flgags);  
ssize_t recvfrom(int sockfd, void*buf, size_t len, int flags,  
       struct sockaddr *src_addr, socklen_t* addrlen); 

recvfrom следует скорректировать из:

   recvfrom(socket_fd, buffer, 2, 0, (struct sockaddr*)&dest_addr, 
             (unsigned int *)sizeof(struct sockaddr_in) == -1)

To:

   recvfrom (socket_fd, buffer, sizeof(buffer), 0, 
            (struct sockaddr*)&dest_addr, &addrlen);
  • Вы не инициализируете dest_addr
  • Массив (eg _buffer_) всегда является типом указателя.
  • Буфер должен быть НАМНОГО больше (динамического размера) в производственной программе, иначе фиксированный размер буфера станет целью для разрушения стека (дыра в безопасности).
person ArrowInTree    schedule 16.12.2012