AsyncSocket just read once? - iphone

I make simple client server with no CLRFdata, but i give header of message with lenght message self. this is my code :
This method send data
- (void)sendMessage:(NSString *)message {
unsigned char lendata = [message length];
senddata = [NSMutableData dataWithBytes: &lendata length:sizeof(lendata)] ;
[senddata appendData:[message dataUsingEncoding:NSUTF8StringEncoding]];
[socket writeData:senddata withTimeout:-1 tag:0];
}
This method read data from socket lenght = 1 byte until long of code on header.
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *message = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
if(bheader){
cdata++;
if(cdata==2){
[data getBytes:&idata];
bheader = NO;
cdata=0;
cmessage = [[NSString alloc] initWithFormat:#""];
}
}
else{
if (message){
cmessage = [[NSString alloc]initWithFormat:#"%#%#",cmessage,message] ;
}
else
NSLog(#"Error converting received data into UTF-8 String");
cdata++;
if(cdata==idata) {
msgComplete=YES;
}
}
if (msgComplete) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:cmessage forKey:kNotificationMessage];
[notificationCenter postNotificationName:kNotification object:self userInfo:userInfo];
cmessage=#"";
msgComplete=NO;
bheader=YES;
cdata=0;
[cmessage release];
}
[sock readDataToLength:1 withTimeout:-1 tag:0];
}
and this method
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag {
[sock readDataToLength:1 withTimeout:-1 tag:0];
}
I'm succes send data and recv data from server use this code,
i try make login and server got data and notification, and i recv message with this code, but after that i cant recv message from server when i send message again, but on TCPDUMP i see any message sent to server and server response with a message ?
could any one fix my code where the problem ?
Thanks.

Related

GCDAsyncSocket "didReadDataWithTag" Never called with NSOperation subclass

In a "getMyFile" method of some XIB file.
I am creating a object of class "A"(subclass of NSOperation) and adding it to a "myFileQueue"(object of NSOperationQueue).
myFileQueue.MaxConcurrentOperationCount = 1;
Problem : didReadDataWithTag" delegate NEVER called in any case.
#import "GCDAsyncSocket.h"
//and all other required classes are imported correctly
//Class : A
#interface A : NSOperation
{
{
GCDAsyncSocket* socket;
dispatch_queue_t dQueue;
BOOL isWorkDone;
}
}
#implementation A {
-main(){
#autoreleasepool {
isWorkDone = NO;
dQueue = dispatch_queue_create(#"MyDQueue", NULL);
socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dQueue];
//NOTE: Even after setting delegateQueue: dispatch_get_main_queue()
//didReadDataWithTag delegate never called
NSError *err = nil;
if (![socket connectToHost:#"192.168.1.142" onPort:12345 error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
do{
[NSThread sleep:0.2];
}while(!isWorkDone)
}
}
- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port
{
NSString* myString= #"testing";
NSData* data=[myString dataUsingEncoding: [NSString defaultCStringEncoding] ];
[socket writeData:data withTimeout:-1 tag:1];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
[socket readDataToData:[GCDAsyncSocket ZeroData] withTimeout:-1 tag:TAG_RESPONSE_HEADER];
}
- (void)socket:(GCDAsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag
{
NSLog(#"didReadDataWithTag called...."); //this method never called in any case
isWorkDone = YES;
}
}

GCDAsyncSocket - Read stream never completes

I am playing with GCDAsyncSocket (MRC / iOS5.1) for a while, especially with "large" files (5 - 10 mb). Unfortunately sometimes the read stream is never completed (e.g. it gets stuck) just a few bytes at the end of the stream; the didReadPartialDataOfLength: stops giving me information and the didReadData is not fired at all.
Here's some of my code (for both writing / reading examples the connection between the host and client have been established)
WRITING
#define kHeadTag 0
#define kDataTag 1
typedef struct {
NSUInteger size;
} head_t;
-(void)sendData:(NSData *)__data {
_sendData = [__data retain];
head_t header;
header.size = __data.length;
[_socket writeData:[NSData dataWithBytes:&header
length:sizeof(header)]
withTimeout:-1
tag:kHeadTag];
}
-(void)socket:(GCDAsyncSocket *)sock
didWriteDataWithTag:(long)tag {
if (tag == kHeadTag) {
[sock writeData:_sendData withTimeout:-1 tag:kDataTag];
[_sendData release];
_sendData = nil;
}
}
READING
-(void)socket:(GCDAsyncSocket *)sock
didReadData:(NSData *)data
withTag:(long)tag {
switch (tag) {
// ------------------------------------- HEAD
case kHeadTag:{
head_t head;
[data getBytes:&head length:sizeof(head)];
_readHead = head;
NSLog(#"Received header (total size = %i bytes)", head.size);
[sock readDataToLength:head.size
withTimeout:-1
tag:kDataTag];
}
break;
// ------------------------------------- BODY
case kDataTag: {
NSLog(#"Data received with %i bytes", data.length);
[sock readDataToLength:sizeof(head_t) withTimeout:-1 tag:kHeadTag];
}
break;
}
};
-(void)socket:(GCDAsyncSocket *)sock
didReadPartialDataOfLength:(NSUInteger)partialLength
tag:(long)tag {
if (tag == kDataTag) {
NSLog(#"Data read with %i bytes", partialLength);
}
};
I hope this is enough code to see what I'm doing wrong or maybe this is a bad practice for writing/reading large chunks of data.
I added
[self.partnerSocket writeData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
at the end of sendData: method, and it works fine for me. You just have to append separator chars at the end of the data.
I can transfer around 48MB of file from one iDevice to other iDevice

CocoaAsyncSockets seems to be failing when calling onSocket:didReadData:withTag

for some reason when I try to call CocoaAsyncSocket's onSocket:didReadData:withTag method, it's failing and not showing data from the read.
appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSError *error = nil;
if (![socket connectToHost:#"199.5.83.63" onPort:11005 error:&error])
{
NSLog(#"Error connecting: %#", error);
}
[socket readDataWithTimeout:10 tag:1];
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[tekMatrixViewController alloc] initWithNibName:#"tekMatrixViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
And here are my methods from the CocoaAsyncSocket Library:
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length])];
NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
NSLog(#"RX length: %d", [data length]);
if(msg)
{
NSLog(#"RX:%#",msg);
}
else
{
NSLog(#"Fail");
}
}
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
NSLog(#"error - disconnecting");
//start reconnecting procedure here...
}
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
{
NSLog(#"disconnected");
}
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(#"connected");
}
When I run my app in the simulator, this is what my output log spits out:
2012-06-08 13:17:30.808 tekMatrix[2793:f803] connected
2012-06-08 13:17:30.815 tekMatrix[2793:f803] RX length: 8
2012-06-08 13:17:30.816 tekMatrix[2793:f803] Fail
onSocket:didConnectToHost:port is called, and NSLog spits out "connected".
onSocket:didReadData:withTag is called, and NSLog spits out "RX length: 8".
also in onSocket:didReadData:withTag, NSLog spits out "Fail".
Correct me if I'm wrong, but it shouldn't "msg" contain the value of the data read from the server? It looks like the Data Read knows that it's expecting a data length of 8, but the data doesn't seem to get stored into the string. I'm very new to iOS and especially socket programming, so this is all new to me. Any help on this subject would be greatly appreciated.
Thanks!
I believe, that the server is delivering data, that isnt UTF-8 encoded.
please try
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
and remove this line:NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length])];
If this doesn't help, here are some more encodings to try:
enum {
NSASCIIStringEncoding = 1,
NSNEXTSTEPStringEncoding = 2,
NSJapaneseEUCStringEncoding = 3,
NSUTF8StringEncoding = 4,
NSISOLatin1StringEncoding = 5,
NSSymbolStringEncoding = 6,
NSNonLossyASCIIStringEncoding = 7,
NSShiftJISStringEncoding = 8,
NSISOLatin2StringEncoding = 9,
NSUnicodeStringEncoding = 10,
NSWindowsCP1251StringEncoding = 11,
NSWindowsCP1252StringEncoding = 12,
NSWindowsCP1253StringEncoding = 13,
NSWindowsCP1254StringEncoding = 14,
NSWindowsCP1250StringEncoding = 15,
NSISO2022JPStringEncoding = 21,
NSMacOSRomanStringEncoding = 30,
NSUTF16StringEncoding = NSUnicodeStringEncoding,
NSUTF16BigEndianStringEncoding = 0x90000100,
NSUTF16LittleEndianStringEncoding = 0x94000100,
NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100,
NSUTF32LittleEndianStringEncoding = 0x9c000100,
NSProprietaryStringEncoding = 65536
};
with NSISOLatin1StringEncoding also being quite common.

NSMutableString append data error

I have AsyncSocket like this.
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *message = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
[data getBytes:&tdata];
if (tdata > 5) {
if(bheader){
if(!charS){
if([message isEqualToString:#"S"]){
CMSG = message;
charS=YES;
}
}
else{
NSMutableString *tmp = [[NSMutableString alloc] initWithString:#""];
[tmp appendString:CMSG]; <<<<< This is code error at loop 2,
[tmp appendString:message]; the first loop success but second is fail
CMSG = tmp;
[tmp release];
}
}
else{
if (message){
cmessage = [[NSString alloc]initWithFormat:#"%#%#",cmessage,message] ;
}
else
NSLog(#"Error converting received data into UTF-8 String");
cdata++;
if(cdata==idata) {
msgComplete=YES;
}
}
if (msgComplete) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:cmessage forKey:kNotificationMessage];
[notificationCenter postNotificationName:kNotification object:self userInfo:userInfo];
cmessage=#"";
CMSG=#"";
msgComplete=NO;
bheader=YES;
cdata=0;
charS=NO;
[cmessage release];
}
}
[sock readDataToLength:1 withTimeout:-1 tag:0];
}
This code fail at second loop at [tmp appendString:CMSG]; Thread 1: Program received signal "SIGABRT"
How fix this error ?
Thanks gurus,
CMSG is assigned to tmp but tmp is released right afterwards. CMSG needs to be retained throughout the loop.
CMSG = tmp; //<< should be CMSG = [tmp retain];
[tmp release];
Now you have another potential problem. You are using a deprecated method here
[data getBytes:&tdata];
if (tdata > 5) {
getBytes: was deprecated because of a potential buffer overrun and the result of getBytes is not appropriate to use for if(tdata > 5). If you want to check the length of bytes get that that from the NSData object.
I see an error that may or may not be the ultimate problem here. In the final conditional statement, you have:
cmessage=#"";
...
[cmessage release];
I don't think you should be releasing that string. I don't actually know all of the ins and outs of NSString objects that are defined in that way (as opposed to stringWithFormat: or initWithString:), but I don't think that you have ownership of that string object. You shouldn't have to release it.
Remove that release message and see if it helps.

message read or not iphone

how can i detect that received sms is read or not by user, i am using CTMessageCenter header also pleas help me..
and also tell me how can i put my application in background continuously....
i think there is no method from which we can found that message is read or not in non jailbreak ...
Ya you can read your incoming message and send also.In your main.m write this code and use three files:CoreTelephony.h,CTMessage.h,CTMessageCenter.h
One problem with this using this way you can't submit your app on app store.
static void callback(CFNotificationCenterRef center, void *observer, NSString* name, const void *object, NSDictionary* info) {
fprintf(stderr, "Notification intercepted: %s\n", [name UTF8String]);
if([name isEqualToString:#"kCTMessageReceivedNotification"] && info)
{
NSNumber* messageType = [info valueForKey:#"kCTMessageTypeKey"];
if([messageType isEqualToNumber:[NSNumber numberWithInt:1]])
{
NSNumber* messageID = [info valueForKey:#"kCTMessageIdKey"];
CTMessageCenter* mc = [CTMessageCenter sharedMessageCenter];
CTMessage* msg = [mc incomingMessageWithId:[messageID intValue]];
NSObject<CTMessageAddress>* phonenumber = [msg sender];
NSString *senderNumber = (NSString*)[phonenumber canonicalFormat];
NSString *sender = (NSString*)[phonenumber encodedString];
CTMessagePart* msgPart = [[msg items] objectAtIndex:0]; //for single-part msgs
NSData *smsData = [msgPart data];
NSString *smsText = [[NSString alloc] initWithData:smsData encoding:NSUTF8StringEncoding];
fprintf(stderr, "SMS Message from %s / %s: \"%s\"\n",[senderNumber UTF8String],[sender UTF8String],[smsText UTF8String]);
}
}
return;
}
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id ct = CTTelephonyCenterGetDefault();
CTTelephonyCenterAddObserver(ct, NULL, callback, NULL, NULL, CFNotificationSuspensionBehaviorHold);
// Start the run loop. Now we'll receive notifications.
[[NSRunLoop currentRunLoop] run];
NSLog(#"you are in main thread");
[pool drain];
printf("Unexpectedly back from CFRunLoopRun()!\n");
[pool release];
}