【发布时间】:2019-07-04 00:26:43
【问题描述】:
我正在开发一个简单的 C++ 程序并希望使用 C 套接字。是否可以通过在 extern "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" 来处理套接字。
【问题讨论】:
-
您可以在
extern "C" { ... }中包含#include -
原则上是的,你可以直接声明所有需要的函数和常量,前者用C链接,而不是包括
sys/socket.h,但为什么要这样做呢?使用标题既安全又容易(实际上不止一个,涵盖了您列出的所有功能)。将其包含在extern "C"块中。 -
你从哪里得到
int connect(int, sockaddr*, int);?这根本不匹配standard。你为什么希望它起作用? -
POSIX specification 定义了
sys/socket.h的(最小)内容,明确表示可以从 C++ 中包含此标头(以及它定义的所有其他标头)。因此,您不需要 这样做。你为什么要这样做? -
@zwol: 练习为另一种语言制作绑定库做准备?这是他应该能够做到的。