when i use GCDasyncsocket to get socket Message from the server(java),it works in the ios simulator(xcode 6,iphone6+); but when i use my iphone6+ connect it to testing, it will lose data when it receive big data,details below
i send a request to the server and get 3 answers
the first data the server answer length is 9 ,and receive 9
the second is 149 and receive 149
the last data the server answer is :2912,but the code shows 1448,
i get the 1448 in the below code:
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSLog(#"receive datas from method 1");
NSLog(#"Data length = %d",[data length]);
...
and when i go deep,the code in the gcdasyncsocket shows the same,code below
if (currentRead->bufferOwner)
{
// We created the buffer on behalf of the user.
// Trim our buffer to be the proper size.
[currentRead->buffer setLength:currentRead->bytesDone];
result = currentRead->buffer;
NSLog(#"if %lu %lu",(unsigned long)currentRead->bytesDone,(unsigned long)result.length);
}
it works well in the simulator,but goes wrong in the real phone;i also test in the iphone4s,it works well most times ~~~~~~~~~~
how strange!
can anyone give me some suggests?
i have got the reason; it is that the protocol split the message ;
i use the method to send the length of the message to tell the protocol how to split it ;
also ,there are some other solutions to solve it ;
and after that ,i also found that the protocol will combine some message,so,when you try to solve it ,you can not just think about the split sitution!
Related
I'm send a string to my server (PHP) with the code below:
NSString* str = #"teststring";
NSData* dataToSend = [str dataUsingEncoding:NSUTF8StringEncoding];
uint8_t *dataBytes = (uint8_t *)[dataToSend bytes];
uint64_t length = dataToSend.length;
[outputStream write:dataBytes maxLength:length];
The problem with this is code, is that I don't receive the string (Server recognize that a user enter and I receive a handshake in Xcode console) I test others codes and works very well (receive data), but in this time I'm trying by my own. I believe I'm not converting the message to the appropriate format, and that's why the message is not being received, am I right? If so how I could convert this message to the appropriate format?
Are you sure the output stream has space for writing that many bytes at the moment when you call the write:... method? You should only call write:... on an output stream from within your stream:handleEvent: delegate method, and only if the event code is NSStreamEventHasSpaceAvailable.
And you must check the result to see how many bytes were actually written. If it is fewer bytes than you sent, you must enqueue the remaining data to resend later, whenever your stream:handleEvent: delegate method gets called again.
For more details, see:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/WritingOutputStreams.html
I am developing one application in which I need to update multiple values like Engine RPM,Speed etc. parameters at a time using OBD connector. I need to achieve asynchronous command/response . For this I am sending commands using [gcdAsyncSocket writeData:data withTimeout:-1 tag:uniqueTag]; asynchronously with unique tag.
But when gcdAsync's delegate method "socketDidReadDatawithTag" is called, it returns the data but it is not proper.e.g. If I have sent one command "010C\r" (Read RPM), and "010D\r" (Speed),with Tag 263 and 264 respectively ,and if I parse the response with tag 264 in socketDidReadDatawithTag , sometimes it returns me the data of RPM. (My response gets Mixed up or OBD Device is unable to handle asynchronous response)
NSLog(#"Command Sent for Async : %#",commandString);
NSData *data = [commandString dataUsingEncoding:NSASCIIStringEncoding];
long obdObjectTag = [obdObject getPIDTag];//Unique Tag
[gcdAsyncSocket writeData:data withTimeout:-1 tag:obdObjectTag];
NSData *readData = [#">" dataUsingEncoding:NSASCIIStringEncoding];
[gcdAsyncSocket readDataToData:readData withTimeout:-1 tag:obdObjectTag];
And in socketdidReadDatawithTag data and tag are mismatched.
The OBD-II connector (I assume it's an ELM-327) cannot really handle asynchronous calls as far as I know.
It cannot handle multiple requests at once. You send 1 command, and the OBD-II device will gather that info from the OBD-bus and return with an answer. Then it will process your next command. Ofcourse, the commands you send end up in a buffer, that will be processed one by one.
I'm thinking this might be a problem for you to make it, but I'm not sure.
I'm not familiar at all with the ios programming and what happens with those tags. You set those tags to identify what paramters are the data for?
In the reply data, you can also see for what parameter it is meant, so in the answer itself you can see that data represents RPM or Speed etc.
I hope the OBD-II part has shed some light on it. Will check this question more for some discussion perhaps.
Basically I write an NSData object:
[asyncSocket writeData:JSONRequestData withTimeout:-1 tag:1];
Which when run, invokes the delegate
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
But for some reason, when the write goes to the buffer... it's not written out to the server.
When I stop my build, I guess the socket decides to write everything and the server ends up seeing it.
How would I fix this? There's no way to flush a CocoaAsyncSocket since it's not necessary...
I've tried adding line endings, like "/n" and all, but that doesn't do anything either.
This is based on user523234's suggestion.
Basically the NSData that you're writing out needs to have some kind of signal to tell the socket that no more data will be coming in.
I appended
[GCDAsyncSocket CRLFData];
to the NSData object
Note: to use the
appendData:
Method, you must convert NSData to NSMutableData.
I have an RFID scanner attached to a RedPark serial cable connected to an iPad app. When people scan their RFID cards, I get a callback with -readBytesAvailable:. However, sometimes it doesn't give me the entire RFID in one call. Sometimes it send it in two calls.
How can I determine if I've received everything? When my code takes the first callback's data and tries to use it, I get an error, because let's say the RFID was "123456789" sometimes I'll get one call with #"12" and a second call with #"3456789". So I try to process #"12" and get a user not found error, then I try to process #"3456789" and get a user not found error.
How can I tell if I'm done reading data? The lengths of the RFIDs can vary from vendor to vendor, so I can't just assume I need to read a certain number of digits.
This is the method I use to receive the data from the scanner through the RedPark:
- (void) readBytesAvailable:(UInt32)length {
NSLog(#"readBytesAvailable: %lu", length);
UInt8 rxLoopBuff[LOOPBACK_TEST_LEN];
[self.rfidManager read:rxLoopBuff Length:length];
NSString *rfid = [[NSString alloc] initWithBytes:rxLoopBuff length:length encoding:NSUTF8StringEncoding];
NSLog(#"rfid=%#", rfid);
[self receivedScanOfRFID:rfid];
}
Serial port gives you no control over packetization. Data is just a stream of bytes with no way to predict which bytes appear in each read call. You have to parse the data stream itself to interpret the contents and understand start/end of your messages. You either need to look for a reliable terminating character or potentially use a timeout approach where you do multiple reads until you get no more data for some period of time. I don't recommend the timeout approach.
I am trying retrieve data from a .php file on a server from within an iPhone OS app. In one method, I employ the following code:
NSString *aString = [[NSString alloc] initWithContentsOfURL:aURL encoding:anEncoding error:nil];
//See what I got
NSLog(aString);
When I run the App it seems like the App runs through the code so fast I doubt that there was enough time for a Data Request to have transpired. The resulting string is totally empty, which further supports my suspicions. What is happening here? Is the app not waiting for the -initWithContentsOfURL to retrieve data from the .php file on my server? If the app does not wait for this method, is there another method I can use to perform a Data Request in a manner that WAITS for the request to be completed before moving onto the next code?
(I've also read a little on NSURLConnection -- is this maybe what I should be looking into instead of -initWithContentsOfURL?)
NSURLConnection is great for getting a file from the web... It doesn't "wait" per se but its delegate callbacks:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
...allow you to be notified when data has been received and when the data has been completely downloaded. This way you can have the App show (if you like) a UIProgressBar as the data comes in and then handle the file as you please when it is completely received.