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 ;
    }

私のサーバーはオンラインであり、コードの後半でアクセスできます(つまり、サーバーへの接続は完全に正常に機能します)。ただし、特定のポートにあるサーバーが到達可能かどうかを検出できるようにしたいです。

また、IPアドレスから「」を削除:5010すると、サーバーがオンラインになっていることを検出し(「」状態にはなりません)、 IPアドレスがないことに対応する!result「」を入力するとサーバーがオフラインになっていることを検出します10.10.10.253私のネットワーク上。

サーバーがオンラインかどうかをどのように判断できますか?

私はこの質問を見てきました:アドレス-サーバーとポート-iOS 5での到達可能性しかし、入力したIPアドレスに関係なく到達可能であることが常に返されるため、機能しません

前もって感謝します

4

1 に答える 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);
}

基本的に、そのポートでサーバーに到達できない場合、ほとんどの場合、CFSocketError ステータスの kCFSocketTimeout を取得します。サーバーから返された特定の応答を解析して、サーバーの準備ができているかどうかを判断する場合、ソケット接続が成功すると ConnectCallBack 関数が呼び出されます。

これは単なる例です。recv() などのメイン スレッドでソケット接続を呼び出して UI をブロックしないようにしてください。

于 2014-05-23T20:07:32.237 に答える