CocoaAsyncSocket 的读写委托不是触发和代码组织
Posted
技术标签:
【中文标题】CocoaAsyncSocket 的读写委托不是触发和代码组织【英文标题】:CocoaAsyncSocket's read and write delegates are not firing & code organization 【发布时间】:2011-06-17 08:03:55 【问题描述】:我正在尝试使用 cocoaasyncsocket 库附带的 echo 服务器示例的修改版本来执行以下操作:
1) 打开与充当服务器的 python 脚本的连接 2) 发送数据 // 有效,但委托不触发 3) 接收数据 // 委托不触发 4) disconnect // 没有断开,显然还在我的线程中
目前我在 didFinishLaunchingWithOptions 委托中打开一个连接,然后尝试在 didConnectToHost 委托中发送数据。然后我尝试读取从客户端返回的数据,然后断开连接。
我能够打开连接并发送数据(服务器验证为已接收),但 didWriteDataWithTag 委托永远不会触发。但是,服务器接收数据。然后服务器会返回一些数据,但 didReadData 也不会触发。
除了读/写委托没有触发之外,我组织代码的方式似乎不正确,但我不确定这在事件驱动系统中的外观与运行循环相比如何(我是事件驱动的东西+网络的新手)。如果我有一系列动作,其各自的完成是由他们的代表触发的,那么代表是否应该共享某种消息 - 即我们收到“xxx”消息,写回“yyy”?我希望有一个功能来管理所有这些。有这样做的规范方法吗?
IPhoneConnectTestAppDelegate.m (sn-ps)
- (void)localConnect
NSError *error = nil;
if (![asyncSocket connectToHost:@"localhost" onPort:5000 error:&error])
DDLogError(@"Error connecting: %@", error);
- (void)disconnect
[asyncSocket setDelegate:nil];
[asyncSocket disconnect];
[asyncSocket release];
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// Setup our socket (GCDAsyncSocket).
dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];
[self localConnect];
// Add the view controller's view to the window and display.
[window addSubview:viewController.view];
[window makeKeyAndVisible];
- (void)onSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
NSString *output = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"didReadData: %@", output);
- (void)onSocket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
NSLog(@"didWriteDataWithTag");
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
NSLog(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port);
if(port == 5000)
NSString *msg = @"q";
NSData *dataOut = [msg dataUsingEncoding:NSASCIIStringEncoding];
[asyncSocket writeData:dataOut withTimeout:-1 tag:0];
[asyncSocket readDataWithTimeout:-1 tag:0];
[self disconnect];
tcpserver.py
# TCP server example
import socket, time
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 5000))
server_socket.listen(5)
print "TCPServer Waiting for client on port 5000"
while 1:
client_socket, address = server_socket.accept()
print "I got a connection from ", address
while 1:
data = client_socket.recv(512)
print "Data from client",data
time.sleep(2)
data = "xxx"
print "Sending data to client",data
client_socket.send (data)
break;
【问题讨论】:
对于 BSD 套接字周围的简单套接字包装器并将这些操作放在工作线程上,我的麻烦要少得多。 【参考方案1】:我知道这是一个已经被接受的答案的老问题,但是为了澄清那些发现这个线程正在寻找东西的人,委托方法没有被调用的原因是因为 GCDAsynchSocket 以 socket:
而不是onsocket:
即:
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
变成:
- (void) socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
【讨论】:
【参考方案2】:朋友的朋友帮我解决了这个问题!我们无法让 GCDAsyncSocket 正常工作(连接和写入,但不能读取)。然而,AsyncSocket 在所有 3 个方面都起作用,并且所有委托都正常工作。
#import "AsyncSocket.h"
#import "tcp_clientViewController.h"
@implementation tcp_clientViewController
@synthesize socket;
-(IBAction)connect:(id)sender
NSLog(@"(IBAction)connect");
NSError *error = nil;
if (![socket connectToHost:@"localhost" onPort:5000 error:&error])
NSLog(@"Error connecting: %@", error);
-(IBAction)send:(id)sender
NSLog(@"(IBAction)send");
char bytes[] = "abcd\r\n";
NSData* data = [[NSData alloc] initWithBytes:bytes length:sizeof(bytes)];
//NSString *msg = @"xxxxx\r\n";
//NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
[socket writeData:data withTimeout:-1 tag:0];
//NSData *data = [asyncSocket readDataWithTimeout:-1 tag:0];
[data release];
[socket readDataToData:[AsyncSocket LFData] withTimeout:-1 tag:0];
- (void)viewDidLoad
// initialize socket
socket = [[AsyncSocket alloc] initWithDelegate:self];
#pragma mark AsyncSocket Delegate Methods
-(void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
NSLog(@"socket:%p didWriteDataWithTag:%@", sock, tag);
- (void)socket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag
NSLog(@"socket:%p didWritePartialDataOfLength:%@ tag:%@", sock, partialLength, tag);
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
NSLog(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port);
- (void)socketDidSecure:(AsyncSocket *)sock
NSLog(@"socket:%p socketDidSecure", sock);
- (void)socketDidDisconnect:(AsyncSocket *)sock withError:(NSError *)err
NSLog(@"socket:%p socketDidDisconnect withError: %@", sock, err);
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
NSString* newStr = [NSString stringWithUTF8String:[data bytes]];
NSLog(@"socket socketDidReadData:%@", newStr);
-(IBAction)disconnect:(id)sender
#pragma mark View stuff
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
- (void)viewDidUnload
- (void)dealloc
self.socket = nil;
[super dealloc];
@end
【讨论】:
【参考方案3】:尝试使用本地 sock 读取命令,并将它们放入写入命令中
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
[sock readDataToData:[AsyncSocket LFData] withTimeout:-1 tag:tag];
【讨论】:
嗯我尝试了[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
(和LFData)并从python服务器发送client_socket.send("xxx\r\n")
并且委托没有触发。写委托也不会触发,但数据会被发送....嗯
如果写委托没有触发,请确保您设置正确
套接字asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];
的初始化是否正确设置了代表? didConnectToHost 委托触发了,所以不是意味着其他 asyncsocket 委托也应该设置吗?我对可可编程很陌生,所以这对我来说有点新。我查看了a SOF question on delegates,但没有澄清。
AsyncSocket 对我来说真的很难设置
我试过了——没用。现在我正专注于让写委托被解雇;我知道数据被发送是因为服务器看到了它!我今天尝试了两种不同的方法。首先,我将服务器接收到的数据长度从 512 更改为每个套接字通信的 4 个,并从客户端发出一条 5 字节的消息。我想也许服务器在确认数据已发送之前正在等待完整的通信。没有工作 - 发送和接收消息,但没有代表解雇。然后,我使用消息代理类修改了 CocoaForScientists 示例,但这也不起作用!以上是关于CocoaAsyncSocket 的读写委托不是触发和代码组织的主要内容,如果未能解决你的问题,请参考以下文章
CDN:无法下载中继 URL:https://cdn.jsdelivr.net/cocoa/Specs/1/d/4/CocoaAsyncSocket/7.6.1/CocoaAsyncSocket.po