是否可以在不包含<sys / socket.h>的情况下使用C套接字?

时间:2019-07-04 00:26:43

标签: c++ c sockets

我正在开发一个简单的C ++程序,并且想使用C套接字。是否可以通过在外部“ C”中声明而不是包含来使用它们?

我们可以使用extern“ C”声明libc绑定,例如write:

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

但是,当声明所需的套接字函数时,结果将不可靠。我发现我可以创建套接字和设置选项,但是connect()总是超时。

这里是使用纯外部“ 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()会超时。

有没有解决的办法,我感兴趣的是看看是否有可能使用纯外部“ C”来使用套接字。

1 个答案:

答案 0 :(得分:0)

您似乎已经从gethostbyname获得了一个IPv6地址,并将其写入sockaddr,从而使缓冲区溢出并破坏了内容。然后,您尝试将IPv6地址的开头部分作为IPv4地址连接,而该IP不想与您对话。

这行还是很疯狂的,但我看不出为什么它会失败:

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

应该是

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