0

我想制作一个在所有接口上都接受 IPv4 和 IPv6 的服务器。

它似乎不适用于任何地址,包括 localhost、127.0.0.1、::1、192.168.1.26。我错过了什么?

根据getaddrinfo(3),因为 ai_family 设置为AI_PASSIVE标志。'返回的套接字地址将包含“通配符地址”'

到目前为止,这是我的代码。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/times.h>
#include <errno.h>


#define MAXBUF  1024

const char* PORTNUM = "687";

int init_address(struct addrinfo* hints)
{
    hints->ai_flags=     AI_PASSIVE;
    hints->ai_family=    AF_UNSPEC;
    hints->ai_socktype=  SOCK_DGRAM;
    hints->ai_protocol=  IPPROTO_UDP;
    return 1;
}

socklen_t init_socket(struct addrinfo* res, int* sockfd)
{
    struct addrinfo* ressave;
    struct sockaddr_in* all_interface;
    socklen_t addrlength;

    ressave=res;
    all_interface = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));

    do {/* each of the returned IP address is tried*/
        (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
        if ((*sockfd)<0)
            continue; /* fail, try next one*/

        if (bind((*sockfd), (struct sockaddr*)all_interface, sizeof(all_interface)) == 0)
            break; /*success*/

        close(*sockfd);

    }while(res->ai_next != NULL  && (res = res->ai_next)!= NULL);

    if(&addrlength)
        addrlength = res->ai_addrlen;

    freeaddrinfo(ressave);
    free(all_interface);

    return addrlength;
}

int doprocessing(char* buffer, size_t buff_size)
{
    return 0;
}

int peak_data(char* buffer, size_t buff_size)
{
    return 0;
}

int main(int argc, char const *argv[])
{
    int sockfd, newsockfd;
    int bytes_read;
    char* port;
    char buffer[MAXBUF];
    pid_t pid;
    socklen_t addrlen, len;
    struct addrinfo* socket_info;
    struct addrinfo* res;
    struct addrinfo* backup_res;
    struct sockaddr* cliaddr;
    int  n;

    socket_info = (struct addrinfo*)malloc(sizeof(struct addrinfo));
    res = (struct addrinfo*)malloc(sizeof(struct addrinfo));

    memset(socket_info, 0, sizeof(struct addrinfo));
    init_address(socket_info);


    if((n = getaddrinfo(NULL, PORTNUM, socket_info, &res)) !=0)
    {
        printf("multi_server: error for %s: %s", PORTNUM, gai_strerror(n));
        exit(0);
    }

    if ((addrlen = init_socket(res, &sockfd)) < 0)
    {
        printf("multi_server: Socket or Bind error");
        exit(0);
    }

    free(socket_info);

    cliaddr=malloc(addrlen);

    len=addrlen;

    printf("\nUDP Server: waiting for connection...");
    while (1) {
        bytes_read = recvfrom(sockfd, buffer, MAXBUF-1, MSG_PEEK, cliaddr, &len);

        if (bytes_read > 0) {
            // a connection has been established
            buffer[MAXBUF] = '\0';
            printf("\nUDP Server: received %d bytes ", bytes_read);
            pid = fork();

            if (pid < 0) {
                perror("UDP Server: ERROR while forking new process.\n");
                exit(1);
            }
            // check if the process ID is zero
            if (pid == 0) {
                // we are now inside the new forked process
                if(peak_data(buffer, bytes_read))
                {
                    doprocessing(buffer, bytes_read);
                }
                printf("Now in %d\n", pid);
                close(sockfd);
                exit(0);
            }
        }
    }
}
4

1 回答 1

1

你没有错过任何东西。它正在接受与您所说的 ::1 的连接?然后它将接受 ipv6 连接。由于 IPv6 向后兼容,如果您创建了正确的 ipv6 套接字,它应该也能够发送和接收 ipv4 数据包。

于 2013-07-23T20:09:49.220 回答