如何在c++;? 我正在用C++ WiSoCube进行实验。我想创建一种方法,在不知道服务器的IP的情况下,我可以用它在网络上查找服务器。为此,我只需通过IP地址192.168.1.0到192.168.1.255循环我的连接方法。但是,每次连接之间的时间非常长,程序倾向于在:connect(nBytes,(sockaddr*)&server,sizeof(server))语句处等待至少30秒(如果不是更长的话)。我的问题如下:为什么会发生这种情况,我如何解决这个问题,是否有一种完全不同的更好的方法来找到服务器
我的连接方法:如何在c++;? 我正在用C++ WiSoCube进行实验。我想创建一种方法,在不知道服务器的IP的情况下,我可以用它在网络上查找服务器。为此,我只需通过IP地址192.168.1.0到192.168.1.255循环我的连接方法。但是,每次连接之间的时间非常长,程序倾向于在:connect(nBytes,(sockaddr*)&server,sizeof(server))语句处等待至少30秒(如果不是更长的话)。我的问题如下:为什么会发生这种情况,我如何解决这个问题,是否有一种完全不同的更好的方法来找到服务器,c++,winsockets,C++,Winsockets,我的连接方法: SOCKET connect(char *ipAdress) { WSAData wsaData; if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) return errorReport("Could not create startup struct"); nBytes = socket(AF_INET, SOCK_STREAM, 0); if (nBytes == SOCKET_ERR
SOCKET connect(char *ipAdress)
{
WSAData wsaData;
if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR)
return errorReport("Could not create startup struct");
nBytes = socket(AF_INET, SOCK_STREAM, 0);
if (nBytes == SOCKET_ERROR)
return errorReport("Socket could not be created");
struct hostent *host_entry;
if ((host_entry = gethostbyname(ipAdress)) == NULL)
return errorReport("Cannot find server.");
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(1337);
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;
if (connect(nBytes, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
WSACleanup();
return errorReport("Failed to connect to server.");
}
if (nBytes == -1)
{
WSACleanup();
disconnect(nBytes);
return errorReport("Could not connect");
}
return 0;
}
另外,请随时告诉我当前连接方法中的任何错误。长延迟是由于套接字在返回调用方之前需要超时造成的。为了减少总的执行时间,您应该让多个工作线程同时连接到单独的IP地址。我会做一项研究,以确定winsock是否支持异步I/O。好的,这里有几件事 首先,connect设计为在服务器繁忙时等待一段时间,然后超时。你可以调整超时长度,尽管我记不清该怎么做了 其次,您的代码将找到一个服务器,但是您如何知道它是您正在寻找的服务器呢?可能是其他应用程序正在同一端口上侦听。除非您只是对任何服务器进行扫描,否则您需要进行一些验证,以确定您在另一端与谁通话
最后,假设您同时编写客户机和服务器,更好的解决方案是让客户机发送广播/多播消息,让服务器(如果有多个服务器的话)侦听并响应该消息。然后,客户端只需等待一段指定的时间,等待响应以确定服务器的位置。服务器IP地址是否随机,您每次都需要这样做?我已经很长时间没有做过任何套接字编程了,但是由于超时等原因,这可能不会变得更好 其他选择:
- 在网络共享上使用IP地址的配置文件如何?这可以在服务器启动时重写
- 将服务器的IP地址设置为静态和硬代码,或放入配置文件中
- 通过DNS或NETBIOS查找计算机的名称
还有,究竟为什么需要扫描IP?即使是动态的,您也应该能够通过其主机名查找ip。请参阅gethostbyname()或getaddrinfo()。我看到您正在使用windows。但是,如果您使用的是Linux,则可以通过组合非阻塞套接字创建一个具有超时的连接函数,并选择:
int connect_with_timeout(int sock, struct sockaddr *addr, int size_addr, int timeout) {
#if defined(Linux)
int error = 0;
fd_set rset;
fd_set wset;
int n;
// set the socket as nonblocking IO
int flags = fcntl (sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
errno = 0;
// we connect, but it will return soon
n = connect(sock, addr, size_addr);
if(n < 0) {
if (errno != EINPROGRESS) {
return -1;
}
} else if (n == 0) {
goto done;
}
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(sock, &rset);
FD_SET(sock, &wset);
struct timeval tval;
tval.tv_sec = timeout;
tval.tv_usec = 0;
// We "select()" until connect() returns its result or timeout
n = select(sock + 1, &rset, &wset, 0, timeout ? &tval : 0);
if(n == 0) {
errno = ETIMEDOUT;
return -1;
}
if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) {
socklen_t len = sizeof(error);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
return -1;
}
} else {
return -1;
}
done:
// We change the socket options back to blocking IO
if (fcntl(sock, F_SETFL, flags) == -1) {
return -1;
}
return 0;
#else
return connect(sock, addr, size_addr);
#endif
}
int connect_with_timeout(int sock,struct sockaddr*addr,int size_addr,int timeout){
#如果已定义(Linux)
整数误差=0;
fd_集rset;
fd_集wset;
int n;
//将套接字设置为非阻塞IO
int flags=fcntl(sock,F_GETFL,0);
fcntl(sock、F|U SETFL、标志| O|U NONBLOCK);
errno=0;
//我们联系上了,但很快就会回来
n=连接(插座、地址、尺寸和地址);
如果(n<0){
if(errno!=EINPROGRESS){
返回-1;
}
}else如果(n==0){
去做;
}
FD_零和rset;
FD_零(和wset);
FD_套装(袜子和rset);
FD_套件(短袜和wset);
结构timeval-tval;
tval.tv_sec=超时;
tval.tv_usec=0;
//我们“选择()”,直到connect()返回其结果或超时
n=选择(sock+1、&rset、&wset、0、超时?&tval:0);
如果(n==0){
errno=ETIMEDOUT;
返回-1;
}
if(FD_-ISSET(sock和rset)| | FD_-ISSET(sock和wset)){
socklen_t len=sizeof(错误);
if(getsockopt(sock、SOL_SOCKET、SO_ERROR、ERROR和len)<0){
返回-1;
}
}否则{
返回-1;
}
完成:
//我们将套接字选项更改回阻塞IO
如果(fcntl(sock,F_SETFL,flags)=-1){
返回-1;
}
返回0;
#否则
返回连接(插座、地址、尺寸和地址);
#恩迪夫
}
当然可以,我很想看看!谢谢我已经下载了,很快会看的,再次感谢!