asyncsocket ipad没有连接到服务器[关闭]

Posted

技术标签:

【中文标题】asyncsocket ipad没有连接到服务器[关闭]【英文标题】:asyncsocket ipad doesn't connect to server [closed] 【发布时间】:2011-11-22 08:59:19 【问题描述】:

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

我有一个运行 asyncsockets 的 iPad 应用程序,我正试图让它连接到我桌面上的服务器,也使用 asyncsockets。 iPad 是专门的 ios 5 并且正在使用 GCD asyncsockets。

正在通过 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);

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

以上是关于asyncsocket ipad没有连接到服务器[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 dispatch_async() 方法时 AsyncSocket 无法连接到主机?

AsyncSocket WHOIS 连接

GCDAsyncSocket - 不接收数据 - AsyncSocket 工作正常

AsyncSocket TLS HOWTO

AsyncSocket 在 iPad 的睡眠模式下崩溃

IPAD忘记密码重置恢复出厂设置