UDP C服务器sendto()错误:无法分配请求的地址

时间:2014-11-17 15:41:09

标签: c networking udp runtime-error server

我正在使用UDP在C中编写基本的客户端/服务器程序。该程序的想法是客户端向服务器发送消息,服务器接收它,然后将其回送给客户端(目标是测量UDP的RTT)。不幸的是,在服务器端,当程序试图调用sendto()来回显消息时,我收到错误“无法分配请求的地址”。

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>

#define SERVER_PORT 7000 
#define MAX_PENDING 10 
#define MAX_LINE 1024000

int main() 
{ 
    struct sockaddr_in sin, sout;
    socklen_t soutLen; 
    char buf[MAX_LINE]; 
    int len;
    int msgLen;
    int s; 
    char *msg;
    if( (s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
        perror("could not establish UDP socket");
        exit(1);
    }

    /* build address data structure */ 
    bzero((char *)& sin, sizeof( sin)); 
    sin.sin_family = AF_INET; 
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port = htons(SERVER_PORT);

    if( (bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0){
        perror("udpServer: bind"); 
        exit( 1); 
    }

    while(1){
        if((msgLen = recvfrom(s, buf, sizeof(buf), 0,(struct sockaddr *)&sout, &soutLen))<0){
            perror("udpServer: recvfrom()"); 
            exit( 1); 
        }

        if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, sizeof(sout)))<0 ){
            perror("udpServer: sendto()"); 
            exit( 1); 
        }
        free(msg);
    }

} 

提前致谢:我对C很新,所以非常感谢任何建议!

1 个答案:

答案 0 :(得分:0)

问题是,您传递给sout的{​​{1}}不正确,因为在将其传递给sendto时您没有正确设置它的大小:

man recvfrom:

recvfrom
     

如果地址不是空指针且套接字不是面向连接的,则填写消息的源地址。 address_len 参数为一个   value-result参数,初始化为与address关联的缓冲区的大小,并在返回时修改以指示地址的实际大小        存储在那里。

当您将 ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len); 传递给&sout时,您还必须告诉recvfrom您传入的结构的大小,以便知道它可以在那里写入多少数据 - recvfrom既是in参数又是out参数。由于您没有初始化soutLen,因此它可能有一些小于结构实际大小的值,这意味着您在soutLen中最终得到的结果无效。

所以你需要初始化sout

soutLen

然后,您应该将此值的大小传递给struct sockaddr_in sin, sout; socklen_t soutLen = sizeof(sout); 而不是sendto(这可能不是必需的,但这是一种很好的做法):

sizeouf(sout)

另外,作为一个注释,您正在释放您从未分配过的 if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, soutLen))<0 ){ 。这是不相关的,但可能会在以后引起问题。

希望这有帮助。