使用 NSNetService 连接到服务器但失败 - 自动套接字断开连接?
问题的新的更简单版本:
我正在尝试使用 Objective-C 客户端连接到 Bonjour 设备并与之通信,但在解析服务(服务器)时遇到问题。最初我尝试做一个更复杂的示例,但我发现即使指定了端口/IP,基本套接字连接也无法正常工作。
我使用 cocoaAsyncSocket 库拥有最简单的代码:
AsyncSocket *xxx = [[[AsyncSocket alloc] initWithDelegate:self] autorelease];
NSError **err;
[xxx connectToHost: @"localhost" onPort: 5000 error: err];
NSLog(@"err=%@",err);
这是我尝试连接的服务器(Python 脚本):
# TCP server with bonjour broadcast!
import select
import sys
import pybonjour
import socket
from time import sleep
#name = sys.argv[1]
#regtype = sys.argv[2]
#port = int(sys.argv[3])
# Bonjour service parameters
name = "TEST"
regtype = "_xxx._tcp."
port = 5000
# Tcp socket stuff
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", port))
server_socket.listen(5)
def register_callback(sdRef, flags, errorCode, name, regtype, domain):
if errorCode == pybonjour.kDNSServiceErr_NoError:
print 'Registered service:'
print ' name =', name
print ' regtype =', regtype
print ' domain =', domain
sdRef = pybonjour.DNSServiceRegister(name = name,
regtype = regtype,
port = port,
callBack = register_callback)
# register bonjour service
print "Registering Bonjour service"
ready = select.select([sdRef], [], [])
print "ready=",ready
if sdRef in ready[0]:
pybonjour.DNSServiceProcessResult(sdRef)
def configLoop():
data = "Entering configuration mode"
client_socket.send (data)
data = "1) Network SSID: "
client_socket.send (data)
ssid = client_socket.recv(512)
print "Network SSID:",ssid
data = "2) Login: "
client_socket.send (data)
login = client_socket.recv(512)
print "Login:",login
data = "3) Password: "
client_socket.send (data)
passw = client_socket.recv(512)
print "Password:",passw
data = "Restarting server and attempting to connect to "+ssid
client_socket.send (data)
sleep(1)
sys.exit(0)
print "TCPServer Waiting for client on port",port
try:
while 1:
client_socket, address = server_socket.accept()
print "I got a connection from ", address
data = "connection!"
client_socket.send (data)
while 1:
data = client_socket.recv(512)
if ( data == 'q' or data == 'Q'):
client_socket.close()
break;
elif (data == 'C' or data == 'config'): # Enter configuration mode
configLoop();
else:
print "RECIEVED:" , data
finally:
sdRef.close()
服务器永远不会看到传入连接。在客户端,错误变量有值或其他东西——不是我所期望的。请帮忙?
旧(更复杂的版本,使用相同的服务器):
我的调试输出基本上表明服务已解决......然后我立即得到套接字断开连接。与此同时,我的服务器坐在那里,没有看到传入的连接。
当我获得初始连接并打印出服务名称时,我已经使用调试器进行了操作,然后它挂起,直到我按“继续”,然后我立即得到套接字断开连接???
我对 Objective-C 和事件驱动编程非常陌生,所以也许我处理错了?我很感激任何建议!
客户端(调试器)输出:
Running…
2011-05-10 14:10:26.822 Client[34709:a0f] TEST
2011-05-10 14:10:26.850 Client[34709:a0f] Socket disconnected
2011-05-10 14:10:29.724 Client[34709:a0f] Could not resolve: {
NSNetServicesErrorCode = -72003;
NSNetServicesErrorDomain = 10;
}
服务器输出:
Registering Bonjour service
ready= ([<DNSServiceRef object at 0x100583290>], [], [])
Registered service:
name = TEST
regtype = _xxx._tcp.
domain = local.
TCPServer Waiting for client on port 5000
客户端代码(ClientController.m,基本上取自 http://www.macresearch.org/cocoa-scientists-part-xxix-message):
#import "ClientController.h"
#import "AsyncSocket.h"
@interface ClientController ()
@property (readwrite, retain) NSNetServiceBrowser *browser;
@property (readwrite, retain) NSMutableArray *services;
@property (readwrite, assign) BOOL isConnected;
@property (readwrite, retain) NSNetService *connectedService;
@property (readwrite, retain) MTMessageBroker *messageBroker;
@end
@implementation ClientController
@synthesize browser;
@synthesize services;
@synthesize isConnected;
@synthesize connectedService;
@synthesize socket;
@synthesize messageBroker;
-(void)awakeFromNib {
services = [NSMutableArray new];
self.browser = [[NSNetServiceBrowser new] autorelease];
self.browser.delegate = self;
self.isConnected = NO;
}
-(void)dealloc {
self.connectedService = nil;
self.browser = nil;
self.socket = nil;
self.messageBroker = nil;
[services release];
[super dealloc];
}
-(IBAction)search:(id)sender {
[self.browser searchForServicesOfType:@"_xxx._tcp." inDomain:@""];
}
-(IBAction)connect:(id)sender {
NSNetService *remoteService = servicesController.selectedObjects.lastObject;
remoteService.delegate = self;
[remoteService resolveWithTimeout:30];
NSLog(@"%@",remoteService.name);
}
-(IBAction)send:(id)sender {
NSData *data = [textView.string dataUsingEncoding:NSUTF8StringEncoding];
NSLog(textView.string);
// Use socket to send raw text data once connected
}
#pragma mark AsyncSocket Delegate Methods
-(void)onSocketDidDisconnect:(AsyncSocket *)sock {
NSLog(@"Socket disconnected");
}
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock {
if ( messageBroker == nil ) {
[sock retain];
return YES;
}
return NO;
}
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
//MTMessageBroker *newBroker = [[[MTMessageBroker alloc] initWithAsyncSocket:socket] autorelease];
//[sock release];
//newBroker.delegate = self;
//self.messageBroker = newBroker;
self.isConnected = YES;
}
#pragma mark Net Service Browser Delegate Methods
-(void)netServiceBrowser:(NSNetServiceBrowser *)aBrowser didFindService:(NSNetService *)aService moreComing:(BOOL)more {
[servicesController addObject:aService];
}
-(void)netServiceBrowser:(NSNetServiceBrowser *)aBrowser didRemoveService:(NSNetService *)aService moreComing:(BOOL)more {
[servicesController removeObject:aService];
if ( aService == self.connectedService ) self.isConnected = NO;
}
-(void)netServiceDidResolveAddress:(NSNetService *)service {
NSError *error;
self.connectedService = service;
self.socket = [[[AsyncSocket alloc] initWithDelegate:self] autorelease];
[self.socket connectToAddress:service.addresses.lastObject error:&error];
}
-(void)netService:(NSNetService *)service didNotResolve:(NSDictionary *)errorDict {
NSLog(@"Could not resolve: %@", errorDict);
}
@end
NEW SIMPLER VERSION OF PROBLEM:
I'm trying to connect to and communicate with a Bonjour device using an Objective-C client and I'm having trouble resolving the service (server). Originally I tried to do a more complicated example, but I found the basic socket connection even with port/ip specified wasn't working.
I have the most barebones possible code using the cocoaAsyncSocket library:
AsyncSocket *xxx = [[[AsyncSocket alloc] initWithDelegate:self] autorelease];
NSError **err;
[xxx connectToHost: @"localhost" onPort: 5000 error: err];
NSLog(@"err=%@",err);
And here's the server I'm trying to connect to (Python script):
# TCP server with bonjour broadcast!
import select
import sys
import pybonjour
import socket
from time import sleep
#name = sys.argv[1]
#regtype = sys.argv[2]
#port = int(sys.argv[3])
# Bonjour service parameters
name = "TEST"
regtype = "_xxx._tcp."
port = 5000
# Tcp socket stuff
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", port))
server_socket.listen(5)
def register_callback(sdRef, flags, errorCode, name, regtype, domain):
if errorCode == pybonjour.kDNSServiceErr_NoError:
print 'Registered service:'
print ' name =', name
print ' regtype =', regtype
print ' domain =', domain
sdRef = pybonjour.DNSServiceRegister(name = name,
regtype = regtype,
port = port,
callBack = register_callback)
# register bonjour service
print "Registering Bonjour service"
ready = select.select([sdRef], [], [])
print "ready=",ready
if sdRef in ready[0]:
pybonjour.DNSServiceProcessResult(sdRef)
def configLoop():
data = "Entering configuration mode"
client_socket.send (data)
data = "1) Network SSID: "
client_socket.send (data)
ssid = client_socket.recv(512)
print "Network SSID:",ssid
data = "2) Login: "
client_socket.send (data)
login = client_socket.recv(512)
print "Login:",login
data = "3) Password: "
client_socket.send (data)
passw = client_socket.recv(512)
print "Password:",passw
data = "Restarting server and attempting to connect to "+ssid
client_socket.send (data)
sleep(1)
sys.exit(0)
print "TCPServer Waiting for client on port",port
try:
while 1:
client_socket, address = server_socket.accept()
print "I got a connection from ", address
data = "connection!"
client_socket.send (data)
while 1:
data = client_socket.recv(512)
if ( data == 'q' or data == 'Q'):
client_socket.close()
break;
elif (data == 'C' or data == 'config'): # Enter configuration mode
configLoop();
else:
print "RECIEVED:" , data
finally:
sdRef.close()
The server never sees an incoming connection. On the client side, the error var has the value or something- nothing what I'd expect. Help please?
OLD (more complicated version, uses the same server):
My debug output basically says the service is resolved... and then I get a socket disconnect immediately after. Meanwhile my server sits there and hasn't seen incoming connections.
I've walked through with the debugger when I get the initial connection and print out the name of the service- and then it hangs until I press continue and then I get a socket disconnect immediately after???
I'm very new to Objective-C and event driven programming, so perhaps I'm handling something wrong? I appreciate any advice!
Client (Debugger) output:
Running…
2011-05-10 14:10:26.822 Client[34709:a0f] TEST
2011-05-10 14:10:26.850 Client[34709:a0f] Socket disconnected
2011-05-10 14:10:29.724 Client[34709:a0f] Could not resolve: {
NSNetServicesErrorCode = -72003;
NSNetServicesErrorDomain = 10;
}
Server output:
Registering Bonjour service
ready= ([<DNSServiceRef object at 0x100583290>], [], [])
Registered service:
name = TEST
regtype = _xxx._tcp.
domain = local.
TCPServer Waiting for client on port 5000
The client code (ClientController.m, basically lifted from http://www.macresearch.org/cocoa-scientists-part-xxix-message):
#import "ClientController.h"
#import "AsyncSocket.h"
@interface ClientController ()
@property (readwrite, retain) NSNetServiceBrowser *browser;
@property (readwrite, retain) NSMutableArray *services;
@property (readwrite, assign) BOOL isConnected;
@property (readwrite, retain) NSNetService *connectedService;
@property (readwrite, retain) MTMessageBroker *messageBroker;
@end
@implementation ClientController
@synthesize browser;
@synthesize services;
@synthesize isConnected;
@synthesize connectedService;
@synthesize socket;
@synthesize messageBroker;
-(void)awakeFromNib {
services = [NSMutableArray new];
self.browser = [[NSNetServiceBrowser new] autorelease];
self.browser.delegate = self;
self.isConnected = NO;
}
-(void)dealloc {
self.connectedService = nil;
self.browser = nil;
self.socket = nil;
self.messageBroker = nil;
[services release];
[super dealloc];
}
-(IBAction)search:(id)sender {
[self.browser searchForServicesOfType:@"_xxx._tcp." inDomain:@""];
}
-(IBAction)connect:(id)sender {
NSNetService *remoteService = servicesController.selectedObjects.lastObject;
remoteService.delegate = self;
[remoteService resolveWithTimeout:30];
NSLog(@"%@",remoteService.name);
}
-(IBAction)send:(id)sender {
NSData *data = [textView.string dataUsingEncoding:NSUTF8StringEncoding];
NSLog(textView.string);
// Use socket to send raw text data once connected
}
#pragma mark AsyncSocket Delegate Methods
-(void)onSocketDidDisconnect:(AsyncSocket *)sock {
NSLog(@"Socket disconnected");
}
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock {
if ( messageBroker == nil ) {
[sock retain];
return YES;
}
return NO;
}
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
//MTMessageBroker *newBroker = [[[MTMessageBroker alloc] initWithAsyncSocket:socket] autorelease];
//[sock release];
//newBroker.delegate = self;
//self.messageBroker = newBroker;
self.isConnected = YES;
}
#pragma mark Net Service Browser Delegate Methods
-(void)netServiceBrowser:(NSNetServiceBrowser *)aBrowser didFindService:(NSNetService *)aService moreComing:(BOOL)more {
[servicesController addObject:aService];
}
-(void)netServiceBrowser:(NSNetServiceBrowser *)aBrowser didRemoveService:(NSNetService *)aService moreComing:(BOOL)more {
[servicesController removeObject:aService];
if ( aService == self.connectedService ) self.isConnected = NO;
}
-(void)netServiceDidResolveAddress:(NSNetService *)service {
NSError *error;
self.connectedService = service;
self.socket = [[[AsyncSocket alloc] initWithDelegate:self] autorelease];
[self.socket connectToAddress:service.addresses.lastObject error:&error];
}
-(void)netService:(NSNetService *)service didNotResolve:(NSDictionary *)errorDict {
NSLog(@"Could not resolve: %@", errorDict);
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我有同样的问题。问题似乎是连接已经就位:“在连接或接受连接时尝试连接。先断开连接”。不幸的是我还无法解决它。有什么想法吗?这可能是延迟或订购流程问题。
编辑 :
实际上,将 connectToAddress 更改为 ConnectToHost 对我来说很成功! :)
I am having the same issue. It seems the problem is that a connection is already in place : "Attempting to connect while connected or accepting connections. Disconnect first". Unfortunately i haven't been able to resolve it yet. Any idea ? It might a delay or ordering process problem.
EDIT :
Actually, changing connectToAddress to ConnectToHost made it for me ! :)