Могу ли я использовать C-сокеты без включения <sys / socket.h>? - PullRequest
0 голосов
/ 04 июля 2019

Я занимаюсь разработкой простой программы на C ++ и хотел бы использовать C-сокеты.Можно ли использовать их, указав внутри внешнего "С", а не включая?

Мы можем использовать extern "C" для объявления привязок libc, таких как write:

extern "C" {
    int write(int fd, const char *buf, int count);
};

Однако при объявлении требуемых функций сокета результаты ненадежны.Я обнаружил, что могу создавать сокеты и устанавливать параметры, однако connect () всегда истекает.

Вот пример использования объявлений чистого extern "C"

gcc extern.cpp -o extern ; ./extern
extern "C" {
    struct  hostent {
        char *  h_name;
        char ** h_aliases;
        int     h_addrtype;
        int     h_length;
        char ** h_addr_list;
    };
    #define h_addr  h_addr_list[0]
    struct in_addr {
        unsigned long s_addr;
    };
    struct sockaddr {
        unsigned short  sa_family;
        char            sa_data[14];
    };
    struct sockaddr_in {
        short            sin_family;
        unsigned short   sin_port;
        struct in_addr   sin_addr;
        char             sin_zero[8];
    };
    void* memset(void*, int, long unsigned int);
    void* memcpy(void*, const void*, long unsigned int);
    int write(int, const char*, int);
    int close(int);
    hostent* gethostbyname(const char*);
    int socket(int, int, int);
    int connect(int, sockaddr*, int);
    int send(int, const char*, int, int);
    int recv(int, char*, int, int);
    int getsockopt(int, int, int, void*, unsigned int*);
    int setsockopt(int, int, int, const void*, unsigned int);
    unsigned short htons(unsigned short);
    void perror(const char*);
    void exit(int);
    #define AF_INET 2
    #define SOCK_STREAM 1
    #define TCP_NODELAY 1
    #define TCP_SYNCNT  7
    #define IPPROTO_TCP 6
};

void error(const char *s) {
    perror(s);
    exit(1);
}

int main() {
    hostent *hp;
    int nodelay = 1;
    int sockfd;
    struct sockaddr_in serv_addr;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        error("socket");
    }
    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char *)&nodelay, sizeof(int));

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(80);
    if((hp = gethostbyname("stackoverflow.com")) == 0) {
        error("gethostbyname");
    }
    memcpy(&serv_addr.sin_addr, hp->h_addr, hp->h_length);

    // Reduce sock timeout
    int synRetries = 2;
    setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &synRetries, sizeof(synRetries));

    // When using extern "C" this seems to timeout
    if (connect(sockfd, (sockaddr*)(&serv_addr), sizeof(struct sockaddr_in)) < 0) {
        close(sockfd);
        error("connect");
    }

    send(sockfd, "GET / HTTP/1.1\r\n\r\n\0", 19, 0);
    char buf[1024];
    recv(sockfd, buf, 1024, 0);
    write(0, buf, 1024);
    close(sockfd);

    return 0;
}

Я ожидаю, что функция connect () разрешится;однако, если я не включу <sys/socket.h> connect () прекратит работу.

Есть ли способ обойти это, мне интересно узнать, возможно ли работать с сокетами, используя чистый extern "C".

1 Ответ

0 голосов
/ 04 июля 2019

Похоже, вы получили адрес IPv6 от gethostbyname и записали его в sockaddr, переполнив буфер и уничтожив вещи. Затем вы попытались подключиться к ведущей части адреса IPv6 в качестве адреса IPv4, и этот IP не хочет с вами разговаривать.

Также эта строка чокнутая, но я не понимаю, почему это не получится:

memset (& serv_addr, '0', sizeof (serv_addr))

Должно быть

memset (& serv_addr, 0, sizeof (serv_addr))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...