C中的UDP服务器/客户端 - sendto错误:协议不支持的地址族

时间:2016-11-15 16:46:42

标签: c sockets unix udp sendto

我正在编写一个简单的说明性UDP服务器客户端。服务器应根据客户端输入计算客户端的网络字节顺序,并将其发送回客户端。我一直在努力修复这个错误一整天。任何帮助都会得到赞赏。这是服务器的启动和输出:

if sys.argv[1] == "h":
    h2s = soup.find_all("h2")
    for h in h2s:
        for s in h.stripped_strings:
            print(s)

客户启动:

./udpserver.out 4545
from.sin_family: 12079
Little Endian

ERROR UDP_SRV_004 - can not send message to client: Address family not supported by protocol

服务器代码:

./udpclient.out localhost 4545

客户代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#define BUFFER_SIZE 80

static void error(char *msg){
    perror(msg);
    exit(1);
}


int main(int argc, char ** argv){

    int socketfd, portno, fromlen, n, length;
    struct sockaddr_in server, from;
    char buffer[BUFFER_SIZE];
    char response[BUFFER_SIZE];
    const char *le = "Little Endian\n";
    const char *be = "Big Endian\n";
    const char *unk = "Unknown \n";
    int cli_family;

    if(argc!=2){
        fprintf(stderr,"Error starting the client, please start server as: %s port\n", argv[0]);
        exit(0);
    }

    if((socketfd=socket(AF_INET,SOCK_DGRAM,0))<0)
        error("ERROR UDP_SRV_001 - can not create socket");

    portno=atoi(argv[1]);

    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_addr.s_addr=INADDR_ANY;
    server.sin_port=htons(portno);

    if(bind(socketfd,(struct sockaddr *)&server,sizeof(server))<0)
        error("ERROR UDP_SRV_002 - can not bind server address to a socket file descriptor");

    bzero(buffer, BUFFER_SIZE);
    bzero(response,BUFFER_SIZE);
    n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);
    if (n<0)
        error("ERROR UDP_SRV_003 - can not receive client's message");

    cli_family=from.sin_family;
    printf("from.sin_family: %d\n", cli_family); 

    if (buffer[0] == 1 && buffer[1] == 2)
        strcpy(response, be);
    else if (buffer[0] == 2 && buffer[1] == 1)
        strcpy(response, le);
    else
        strcpy(response, unk);

    length=strlen(response);
    printf("%s\n",response);

    n=sendto(socketfd,response,length,0,(struct sockaddr *)&from,fromlen);
    if(n<0)
        error("ERROR UDP_SRV_004 - can not send message to client");


    return 0;
}

1 个答案:

答案 0 :(得分:5)

在服务器中,您在调用fromlen之前未能初始化sendto。因此,from未填充。

来自man page

  

如果src_addr不为NULL,则底层协议提供   源地址,填写此源地址。当src_addr为时   NULL,没有填写;在这种情况下,不使用addrlen,和   也应该是NULL。 参数addrlen是一个值 - 结果参数,   调用者应该在调用大小之前初始化   缓冲区与src_addr相关联,并在返回时进行修改以指示   源地址的实际大小。返回的地址是   如果提供的缓冲区太小,则截断;在这种情况下,addrlen   将返回一个大于提供给调用的值。

recvfrom函数尝试读取fromlen的值,但由于未初始化,因此您调用undefined behavior

初始化fromlen,这将解决问题。

fromlen = sizeof from;
n=recvfrom(socketfd,buffer,BUFFER_SIZE-1,0,(struct sockaddr *)&from,&fromlen);