【问题标题】:UDP - Error in sendto(): Address family not supported by protocolUDP - sendto() 中的错误:协议不支持地址系列
【发布时间】:2019-02-01 06:54:47
【问题描述】:

以下代码是使用 UDP 套接字的编程示例。

有3个.c源文件(Client_UDP.cServer_UDP.cMessage_UDP.c)和1个.h头文件(Prototype.h)。

我希望Server和Client只通过Message_UDP中的函数进行通信。

事情的经过好像是这样的:

  1. 客户端向服务器发送第一个数据包/消息。
  2. 服务器收到客户端发来的数据包。
  3. 服务器尝试发送响应包,但显示错误:"Error in sendto(): Address family not supported by protocol"

有人知道为什么吗?我该如何解决这个问题?

Client_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

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

    int fd_socket;

    struct sockaddr_in server;      
    socklen_t length_server = sizeof (server);

    fd_socket = socket(AF_INET, SOCK_DGRAM, 0);
    Error_A(fd_socket, "Error in socket()");

    server.sin_port = htons(8888);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    // send packet to server
    function_SEND(fd_socket, server, length_server, "CLIENT");

    // receive packet from server
    function_RECEIVE(fd_socket, server, length_server, "CLIENT");

    close(fd_socket);
    return EXIT_SUCCESS;
}

Server_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

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

    int fd_socket;
    int rv; // return value

    struct sockaddr_in server;
    struct sockaddr_in client;

    socklen_t length_server = sizeof (server);
    socklen_t length_client = sizeof (client);

    fd_socket = socket(AF_INET, SOCK_DGRAM, 0);
    Error_A(fd_socket, "Errore in socket()");

    server.sin_port = htons(8888);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;

    rv = bind(fd_socket, (struct sockaddr *) &server, length_server);
    Error_A(rv, "Error in bind()");

    // receive packet from client
    function_RECEIVE(fd_socket, client, length_client, "SERVER");

    // send packet to client
    function_SEND(fd_socket, client, length_client, "SERVER");

    close(fd_socket);
    return EXIT_SUCCESS;
}

Message_UDP.c

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Prototype.h"

void Error_A(int return_value, char *error_message) {

    if (return_value < 0) {
        perror(error_message);
        exit(EXIT_FAILURE);
    }
}

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender) {

    int rv; // return value
    char packet[100] = "PACKET";

    // send packet
    rv = sendto(fd_socket, packet, 100, 0, (struct sockaddr *) &host, length_host);
    Error_A(rv, "Error in sendto()");
    printf("<%s> -- package sent: <%s> \n", sender, packet);
}

void function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver) {

    int rv; // return value
    char packet[100] = "";

    // receive packet
    rv = recvfrom(fd_socket, packet, 100, 0, (struct sockaddr *) &host, &length_host);
    Error_A(rv, "Errore in recvfrom()");
    printf("<%s> -- packet received: <%s> \n", receiver, packet);
}

原型.h

void Error_A(int return_value, char *error_message);

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender);

void function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver);

这是客户端输出:

CLIENT -- 发送的包:PACKET

这是服务器输出:

SERVER -- 收到的包:PACKET

sendto() 出错:协议不支持地址族

【问题讨论】:

  • 与您的问题无关,但您知道端口号应该按网络字节顺序排列吗? IE。你需要使用例如server.sin_port = htons(8888);
  • 与您的问题更相关,不要忘记 C 中函数的参数是 按值 传递的。这意味着函数中的参数是传入的原始值的副本。修改副本不会修改原始值。想一想为什么需要在对recvfrom 的调用中将指针 传递给套接字地址结构,并对在C 中模拟通过引用传递 进行一些研究。
  • 不抱歉...我现在更正它
  • 你的意思是创建一个指向像'struct sockaddr_in *client'这样的结构的指针,然后修改函数'function_RECEIVE()'来传递它吗?
  • 不,client 仍然可以像现在一样是结构对象,但您应该修改您的 function_RECEIVE 以期望指针,并像将结构传递给 recvfrom 一样传递它。跨度>

标签: c sockets udp sendto


【解决方案1】:

我可能遗漏了一些明显的东西。这是我注意到的一点。在您的 Server_UDP.c 中,客户端 没有初始化。 我看到声明 struct sockaddr_in client;,但没有赋值。在这里,我假设客户端将被分配相同的端口号和环回 IP 地址,如下所示

client.sin_port = 8888;
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr("127.0.0.1");

这可能是服务器发送失败的原因

【讨论】:

  • 部分正确,因为client 结构未初始化。但是,它不应该被初始化,而是应该通过调用 recvfrom 来初始化,因为我在对该问题的第二条评论中指出的原因,这不会发生。
  • 是的,它部分工作!服务器发送数据包,但现在是客户端没有收到数据包!
【解决方案2】:

我在Prototype.h中添加了这个结构:

struct Host {
    struct sockaddr_in host;
    socklen_t length_host;
} host_return;

void Error_A(int return_value, char *error_message);

void function_SEND(int fd_socket, struct sockaddr_in host, int length_host, char *sender);

struct Host function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver);

Message_UDP.c 中更改 function_RECEIVE() 如下:

struct Host function_RECEIVE(int fd_socket, struct sockaddr_in host, int length_host, char* receiver) {

    int rv; // return value
    char packet[100] = "";

    // receive packet
    rv = recvfrom(fd_socket, packet, 100, 0, (struct sockaddr *) &host, &length_host);
    Error_A(rv, "Errore in recvfrom()");
    printf("%s -- packet received: %s \n", receiver, packet);

    host_return.host = host;
    host_return.length_host = length_host;

    return host_return;
}

Server_UDP.c 中的代码这样写:

// receive packet from client
host_return = function_RECEIVE(fd_socket, client, length_client, "SERVER");
    
// send packet to client
function_SEND(fd_socket, host_return.host, host_return.length_host,"SERVER");

而不是

// receive packet from client
function_RECEIVE(fd_socket, client, length_client, "SERVER");

// send packet to client
function_SEND(fd_socket, client, length_client, "SERVER");

它似乎工作,因为输出是(但我希望我没有运气):

CLIENT -- 发送的数据包:PACKET

CLIENT -- 收到的数据包:PACKET

服务器:

SERVER -- 收到的数据包:PACKET

SERVER -- 发送的数据包:PACKET

【讨论】:

  • 还有一个问题,length_client 无法正确初始化。
  • 我希望这个更正是正确的。否则任何线索如何正确初始化“length_client”?
猜你喜欢
  • 2017-03-29
  • 2012-12-03
  • 1970-01-01
  • 2018-11-01
  • 2012-03-21
  • 1970-01-01
  • 2013-02-04
  • 2013-12-20
  • 2013-11-21
相关资源
最近更新 更多