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 无法连接到主机?