1

我想知道我的服务器是否通过我的 ios 应用程序在线。这就是我正在做的事情:

Boolean result;
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFDataRef)(serverIPAddress)); //serverIPAdress = "10.10.10.100:5010"

    if(hostRef) {
        result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
    }

    if (!result) { //This means that the host was unreachable        
        return ;
    }

我的服务器在线,我可以稍后在代码中访问它(这意味着我与服务器的连接工作得很好)。但是,我希望能够检测我的服务器在某个端口上是否可以访问。

另外,如果我:5010从IP地址中删除“”,它会检测到我的服务器在线(它不会进入“ !result”条件)并且如果我输入“ 10.10.10.253”对应于没有IP地址,则检测到我的服务器离线在我的网络上。

如何确定我的服务器是否在线?

我看过这个问题:Reachability with Address - Server AND Port - iOS 5但它不起作用,因为无论我输入什么 IP 地址,它总是返回它是可访问的

提前致谢

4

1 回答 1

1

一种方法可能是打开到特定端口的套接字连接,以查看是否得到任何响应。如果不是,则目的地不可到达。例如

#include <arpa/inet.h> //for PF_INET, SOCK_STREAM, IPPROTO_TCP etc

CFRunLoopSourceRef gSocketSource;
void ConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
    UInt8 buffer[1024];
    bzero(buffer, sizeof(buffer));
    CFSocketNativeHandle sock = CFSocketGetNative(socket); // The native socket, used recv()

    //check here for correct connect output from server
    recv(sock, buffer, sizeof(buffer), 0);
    printf("Output: %s\n", buffer);

    if (gSocketSource)
    {
        CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
        if (CFRunLoopContainsSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode))
        {
            CFRunLoopRemoveSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode);
        }
        CFRelease(gSocketSource);
    }

    if (socket) //close socket
    {
        if (CFSocketIsValid(socket))
        {
            CFSocketInvalidate(socket);
        }
        CFRelease(socket);
    }
}

void ConnectSocket()
{
    //socket
    CFSocketContext context = {0, NULL, NULL, NULL, NULL};
    CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack , (CFSocketCallBack)ConnectCallBack, &context);

    //address
    struct sockaddr_in socketAddress;
    memset(&socketAddress, 0, sizeof(socketAddress));
    socketAddress.sin_len = sizeof(socketAddress);
    socketAddress.sin_family = AF_INET;
    socketAddress.sin_port = htons(5010);
    socketAddress.sin_addr.s_addr = inet_addr("10.10.10.253");

    gSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, theSocket, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), gSocketSource, kCFRunLoopDefaultMode);

    CFDataRef socketData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&socketAddress, sizeof(socketAddress));
    CFSocketError status = CFSocketConnectToAddress(theSocket, socketData, 30); //30 second timeout
    //check status here
    CFRelease(socketData);
}

基本上,如果服务器在该端口上无法访问,您很可能会得到一个 kCFSocketTimeout 用于 CFSocketError 状态。如果您希望解析来自服务器的特定响应以确定服务器是否已准备好,则将在成功的套接字连接时调用 ConnectCallBack 函数。

这只是一个简单的例子,请确保不要通过在主线程上调用套接字连接来阻塞 UI,例如 recv()

于 2014-05-23T20:07:32.237 回答