Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c++;? 我正在用C++ WiSoCube进行实验。我想创建一种方法,在不知道服务器的IP的情况下,我可以用它在网络上查找服务器。为此,我只需通过IP地址192.168.1.0到192.168.1.255循环我的连接方法。但是,每次连接之间的时间非常长,程序倾向于在:connect(nBytes,(sockaddr*)&server,sizeof(server))语句处等待至少30秒(如果不是更长的话)。我的问题如下:为什么会发生这种情况,我如何解决这个问题,是否有一种完全不同的更好的方法来找到服务器_C++_Winsockets - Fatal编程技术网

如何在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查找计算机的名称

如果您知道服务器在子网中,为什么不发送一条广播消息,将本地接收端口号作为消息数据?然后,服务器可以简单地侦听此消息并连接回该端口,或者将其自己的配置数据发送回该端口,以便客户端可以直接连接。这样,您只需发送一条消息,而无需在256个IP地址上循环。

我在过去的“人人都有端口139”开放日就成功地完成了这项工作

我发现使用多个线程(遗憾的是,我使用了大约500个线程,但这只是一次尝试,只是为了好玩),在尝试连接之前我ping了服务器,这使我能够每秒通过几个thourand IP

我还有源代码(C++),如果你想查看,请给我留言


还有,究竟为什么需要扫描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;
#否则
返回连接(插座、地址、尺寸和地址);
#恩迪夫
}

当然可以,我很想看看!谢谢我已经下载了,很快会看的,再次感谢!