【发布时间】:2013-11-19 19:58:05
【问题描述】:
编辑::
所以我在下面接受的答案实际上并不是问题。我通过wireshark 验证了对等点确实通过TCP 传输以进行torrent 下载。所以我应该可以连接,但所有尝试都超时......
所以我正在用 C++ 制作一个 bittorrent 客户端,并且我正在使用 BSD 套接字库进行所有网络通信。我有一些代码可以通过 TCP 连接到对等方,但每次尝试都会超时。我 100% 确定对等点对我要下载的文件有效,我开始在传输中下载文件,并且正在连接相同的对等点。
这是我的连接代码,第一部分只是将一堆对等点添加到向量中,以便我可以对其进行迭代并尝试每个对等点:
(注意“所有大写的系统调用只是用于错误处理目的的包装函数。那里没有发生任何有趣的事情。)
char * HOST;
uint16_t PORT;
std::vector<char *> all_ips;
std::vector<uint16_t> all_ports;
all_ips.push_back("213.112.225.102");
all_ports.push_back(18715);
uint32_t i = 0;
for (; i < all_ips.size(); i++) {
HOST = all_ips[i];
PORT = all_ports[i];
struct sockaddr * saddr;
struct sockaddr_in addr;
struct addrinfo hints, * ai, * it;
char strportnum[25];
memset(&hints, '\0', sizeof(hints));
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
snprintf(strportnum, 10, "%d", PORT);
GetAddrInfo(HOST, strportnum, &hints, &ai);
for (it = ai; it != NULL; it = it->ai_next) {
if ((sockFd = Socket(AF_INET, SOCK_STREAM, 0)) != -1) {
saddr = ai->ai_addr;
saddr->sa_family = AF_INET;
int res;
long arg;
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
// Set non-blocking
if( (arg = fcntl(sockFd, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
exit(0);
}
arg |= O_NONBLOCK;
if( fcntl(sockFd, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
exit(0);
}
// Trying to connect with timeout
res = Connect(sockFd, saddr, sizeof(*saddr));
if (res < 0) {
if (errno == EINPROGRESS) {
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
//Set timeouts
tv.tv_sec = 20;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(sockFd, &myset);
res = Select(sockFd + 1, NULL, &myset, NULL, &tv);
if (res < 0 && errno != EINTR) {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
break;
}
else if (res > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(sockFd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
break;
}
// Check the value returned...
if (valopt) {
fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt));
break;
}
break;
}
else {
fprintf(stderr, "Timeout in select() - Cancelling!\n");
break;
}
} while (1);
}
else {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
break;
}
}
// Set to blocking mode again...
if( (arg = fcntl(sockFd, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
break;
}
arg &= (~O_NONBLOCK);
if(fcntl(sockFd, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
break;
}
}
}
freeaddrinfo(ai);
}
我一直使用这个网站作为非阻塞套接字的指南: http://developerweb.net/viewtopic.php?id=3196
【问题讨论】:
-
当您尝试连接到 localhost 服务时会发生什么?例如。用 netcat 启动一个监听器,然后用你的代码连接?
-
您是否正在尝试使用 TCP 连接到期望与“说”UDP 的端口?
-
我要做的事情:使用 strace -v 查看系统调用的确切参数。使用 tcpdump/wireshark 查看发送/接收的数据包。通过这种方式可以轻松检测到诸如未进行正确字节交换之类的琐碎问题。
-
您应该找到一个可以连接的标准客户端程序。 Telnet 或 netcat 都可以。然后你开始观察使用wireshark的工作连接,以及你的代码的非工作连接。比较工作包和非工作包的字段,试着找出它们之间的区别。
标签: c++ c sockets tcp bittorrent