ios - asyncsocket ipad 无法连接到服务器

标签 ios ipad networking client-server asyncsocket

<分区>

我的应用程序在尝试连接到主机时超时。超时时间设置为无限制,所以我认为客户端真的根本无法连接。

我有一个运行 asyncsockets 的 iPad 应用程序,我正试图让它连接到我桌面上也使用 asyncsockets 的服务器。 iPad 特别适用于 iOS 5,并且使用 GCD 异步套接字。

正在通过 NSRunLoop 调用服务器。它没有从客户端接收任何形式的连接(没有像用于 telnet 连接那样捕获断点)。

我可以很好地从其他机器远程登录到服务器。我还可以将 iPad 客户端连接到端口:80 上的 host:google.com 就好了。

我已经尝试将 iPad 连接到端口 8080、4500 和 50000 上的服务器,但都没有成功(尽管它们都适用于 telnet)。

我相信服务器代码中有某些东西导致了这个,但我不确定。

我的服务器代码来自此处的示例:http://mysterycoconut.com/blog/2010/07/tweak-away/

我的客户端代码是从 asyncsockets 存储库提供的示例 GCD 代码中修改的 HTTP 客户端代码:https://github.com/robbiehanson/CocoaAsyncSocket/blob/master/Examples/GCD/SimpleHTTPClient/Mobile/SimpleHTTPClient/SimpleHTTPClientAppDelegate.m

这是我的服务器代码:

  - (id) init;
{
    self = [super init];
    if (self != nil)
    {
        debugServer = [[AsyncSocket alloc] initWithDelegate:self];
        connectedClients = [[NSMutableArray alloc] initWithCapacity:1];
        running = false;
    }
    return self;
}

- (void) dealloc;
{
    [self stop];
    [connectedClients release];
    [debugServer release];
    [super dealloc];
}

- (void) startOnPort
{
    if (running) return;

    if (_port < 0 || _port > 65535)
        _port = 0;

    NSError *error = nil;
    if (![debugServer acceptOnPort:_port error:&error])
        return;

    NSLog(@"My Awesome Debug Server has started on port %hu", [debugServer localPort]);

    running = true;
}


- (void) stop;
{
    if (!running) return;

    [debugServer disconnect];
    for (AsyncSocket* socket in connectedClients)
        [socket disconnect]; 

    running = false;
}


- (void) setPort:(int)in_port{
    _port = in_port;
}

- (void)onSocket:(AsyncSocket *)socket didAcceptNewSocket:(AsyncSocket *)newSocket;
{
    [connectedClients addObject:newSocket];
}


- (void)onSocketDidDisconnect:(AsyncSocket *)socket;
{
    [connectedClients removeObject:socket];
}

- (void)onSocket:(AsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port;
{
    NSLog(@"Accepted client %@:%hu", host, port);

    NSData *welcomeData = [@"Welcome to my Awesome Debug Server\r\n\r\n" 
                           dataUsingEncoding:NSUTF8StringEncoding];
    [socket writeData:welcomeData withTimeout:-1 tag:WelcomeMsgTag];

    [socket readDataWithTimeout:-1 tag:GenericMsgTag];
}


- (void)onSocket:(AsyncSocket *)socket didReadData:(NSData *)data withTag:(long)tag;
{
    NSString *tmp = [NSString stringWithUTF8String:[data bytes]];
    NSString *input = [tmp stringByTrimmingCharactersInSet:
                       [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    NSLog(@"%@",input);

    if ([input isEqualToString:@"exit"])
    {
        NSData *byeData = [@"Bye!\r\n" dataUsingEncoding:NSUTF8StringEncoding];
        [socket writeData:byeData withTimeout:-1 tag:GenericMsgTag];
        [socket disconnectAfterWriting];
        return;
    }

    [socket readDataWithTimeout:-1 tag:GenericMsgTag];
}

@end

...这是我的客户端代码:

- (id) init
{
    if (self = [super init]) {
    // AsyncSocket optionally uses the Lumberjack logging framework.
    // 
    // Lumberjack is a professional logging framework. It's extremely fast and flexible.
    // It also uses GCD, making it a great fit for GCDAsyncSocket.
    // 
    // As mentioned earlier, enabling logging in GCDAsyncSocket is entirely optional.
    // Doing so simply helps give you a deeper understanding of the inner workings of the library (if you care).
    // You can do so at the top of GCDAsyncSocket.m,
    // where you can also control things such as the log level,
    // and whether or not logging should be asynchronous (helps to improve speed, and
    // perfect for reducing interference with those pesky timing bugs in your code).
    // 
    // There is a massive amount of documentation on the Lumberjack project page:
    // https://github.com/CocoaLumberjack/CocoaLumberjack
    // 
    // But this one line is all you need to instruct Lumberjack to spit out log statements to the Xcode console.

    [DDLog addLogger:[DDTTYLogger sharedInstance]];

    // Create our GCDAsyncSocket instance.
    // 
    // Notice that we give it the normal delegate AND a delegate queue.
    // The socket will do all of its operations in a background queue,
    // and you can tell it which thread/queue to invoke your delegate on.
    // In this case, we're just saying invoke us on the main thread.
    // But you can see how trivial it would be to create your own queue,
    // and parallelize your networking processing code by having your
    // delegate methods invoked and run on background queues.

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    // Now we tell the ASYNCHRONOUS socket to connect.
    // 
    // Recall that GCDAsyncSocket is ... asynchronous.
    // This means when you tell the socket to connect, it will do so ... asynchronously.
    // After all, do you want your main thread to block on a slow network connection?
    // 
    // So what's with the BOOL return value, and error pointer?
    // These are for early detection of obvious problems, such as:
    // 
    // - The socket is already connected.
    // - You passed in an invalid parameter.
    // - The socket isn't configured properly.
    // 
    // The error message might be something like "Attempting to connect without a delegate. Set a delegate first."
    // 
    // When the asynchronous sockets connects, it will invoke the socket:didConnectToHost:port: delegate method.

    NSError *error = nil;

#if USE_SECURE_CONNECTION
    uint16_t port = 443; // HTTPS
#else
    uint16_t port = 8080;  // HTTP
#endif

    DDLogVerbose(@"port: %d\t host: %@",port,@"130.85.92.12");

    if (![asyncSocket connectToHost:@"130.85.92.12" onPort:port error:&error])
    {
        DDLogError(@"Unable to connect to due to invalid configuration: %@", error);
    }
    else
    {
        DDLogVerbose(@"Connecting...");
    }

#if USE_SECURE_CONNECTION

    // The connect method above is asynchronous.
    // At this point, the connection has been initiated, but hasn't completed.
    // When the connection is establish, our socket:didConnectToHost:port: delegate method will be invoked.
    // 
    // Now, for a secure connection we have to connect to the HTTPS server running on port 443.
    // The SSL/TLS protocol runs atop TCP, so after the connection is established we want to start the TLS handshake.
    // 
    // We already know this is what we want to do.
    // Wouldn't it be convenient if we could tell the socket to queue the security upgrade now instead of waiting?
    // Well in fact you can! This is part of the queued architecture of AsyncSocket.
    // 
    // After the connection has been established, AsyncSocket will look in it's queue for the next task.
    // There it will find, dequeue and execute our request to start the TLS security protocol.
    // 
    // The options passed to the startTLS method are fully documented in the GCDAsyncSocket header file.
    // The deusty server only has a development (self-signed) X.509 certificate.
    // So we tell it not to attempt to validate the cert (cause if it did it would fail).

    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
                                                        forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];

    [asyncSocket startTLS:options];

#endif
    }

    return self;
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
    DDLogVerbose(@"socket:didConnectToHost:%@ port:%hu", host, port);

    // HTTP is a really simple protocol.
    // 
    // If you don't already know all about it, this is one of the best resources I know (short and sweet):
    // http://www.jmarshall.com/easy/http/
    // 
    // We're just going to tell the server to send us the metadata (essentially) about a particular resource.
    // The server will send an http response, and then immediately close the connection.

    NSString *msg = @"iOS client connected\r\n\r\n";
    NSData *msgdata = [msg dataUsingEncoding:NSUTF8StringEncoding];

    [asyncSocket writeData:msgdata withTimeout:-1.0 tag:0];

    // Side Note:
    // 
    // The AsyncSocket family supports queued reads and writes.
    // 
    // This means that you don't have to wait for the socket to connect before issuing your read or write commands.
    // If you do so before the socket is connected, it will simply queue the requests,
    // and process them after the socket is connected.
    // Also, you can issue multiple write commands (or read commands) at a time.
    // You don't have to wait for one write operation to complete before sending another write command.
    // 
    // The whole point is to make YOUR code easier to write, easier to read, and easier to maintain.
    // Do networking stuff when it is easiest for you, or when it makes the most sense for you.
    // AsyncSocket adapts to your schedule, not the other way around.

#if READ_HEADER_LINE_BY_LINE

    // Now we tell the socket to read the first line of the http response header.
    // As per the http protocol, we know each header line is terminated with a CRLF (carriage return, line feed).

    [asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
#else

    // Now we tell the socket to read the full header for the http response.
    // As per the http protocol, we know the header is terminated with two CRLF's (carriage return, line feed).

    [asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];

#endif
}

- (void)socketDidSecure:(GCDAsyncSocket *)sock
{
    // This method will be called if USE_SECURE_CONNECTION is set

    DDLogVerbose(@"socketDidSecure:");
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    DDLogVerbose(@"socket:didWriteDataWithTag:");
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    DDLogVerbose(@"socket:didReadData:withTag:");

    NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    NSLog(@"%@",httpResponse);

#if READ_HEADER_LINE_BY_LINE

    DDLogInfo(@"Line httpResponse: %@", httpResponse);

    // As per the http protocol, we know the header is terminated with two CRLF's.
    // In other words, an empty line.

    if ([data length] == 2) // 2 bytes = CRLF
    {
        DDLogInfo(@"<done>");
    }
    else
    {
        // Read the next line of the header
        [asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1.0 tag:0];
    }

#else

    DDLogInfo(@"Full httpResponse: %@", httpResponse);

#endif

    [httpResponse release];
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    // Since we requested HTTP/1.0, we expect the server to close the connection as soon as it has sent the response.

    DDLogVerbose(@"socketDidDisconnect:withError: \"%@\"", err);
}

我四处寻找答案,但没有成功。我认为最好的做法是问问大家,而不是绞尽脑汁自己解决。

最佳答案

解决方案是以不同方式连接到本地网络。我使用的网络需要登录才能进行本地访问,但为广域网访问提供了“访客”连接。设备 (iPad) 自动连接为“访客”,我需要手动登录。

因此,如果您无法使用此 API 进行连接,请检查您是如何连接到网络的!

关于ios - asyncsocket ipad 无法连接到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8224204/

相关文章:

ios - Swift - 即使控件可见, View 也不显示/更新控件

ios - 在 iPhone 上运行分割 View 应用程序时 Xcode 9 崩溃

android - Android 设备的 VLAN

javascript - vis.js 网络——工具提示/弹出窗口的固定位置

linux - 事件套接字的 '{tcp_error, Socket, etimedout}' 消息从何而来?

ios - 如何在 Swift 中将按钮图像设置为 nil?

ios - 无法创建映射策略 - iOS 核心数据

iphone - 在 CGPath 之间着色

iphone - ipad 未调用 didSelectAnnotationView

iphone - 如何获取关系键