I have some problem with my objective-c app. I want to convert input stream to textfield.text in objective-c.
I have tcp client with input stream and output stream. I want to use data from input stream and show them in uitextfield.
Can I use something like that:
temperatura.text = [inputStream read:buffer maxLength:sizeof(buffer)];
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
NSLog(#"stream event %i", streamEvent);
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[1024];
int len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(#"server said: %#", output);
}
}
}
}
break;
I'm using this client. I want to use data from 'output' to get them on textfield.
Following line of code will return an int
[inputStream read:buffer maxLength:sizeof(buffer)]
Following line of code needs a NSString not int
temperatura.text
So you will have to typecast [inputStream read:buffer maxLength:sizeof(buffer)] to a string before you assign to temperatura.text . You can use following to typecast:
temperatura.text = [NSString stringWithFormat:#"%d",[inputStream read:buffer maxLength:sizeof(buffer)]];
A simple typecast example is :
NSString *string = [NSString stringWithFormat:#"%d", theinteger];
Please note that I have not tested this code for proper syntax, but this could be a solution. Let me know if you face any problems.
Thanks
Refer Folowing Code
(void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
if(!_data) {
_data = [[NSMutableData data] retain];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)stream read:buf maxLength:1024];
if(len) {
[_data appendBytes:(const void *)buf length:len];
// bytesRead is an instance variable of type NSNumber.
[bytesRead setIntValue:[bytesRead intValue]+len];
} else {
NSLog(#"no buffer!");
}
break;
**
temperatura.text = [[NSString alloc] initWithBytes:[_data bytes] length:[_data length] encoding:NSUTF8StringEncoding]
**
Related
I'd like to create global variable that will contain answers from socket connection.
This is my code:
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"192.168.0.10", 35000, &readStream, &writeStream);
self.inputStream = objc_unretainedObject(readStream);
self.outputStream = objc_unretainedObject(writeStream);
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
}
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(#"Połączono\n");
break;
case NSStreamEventHasBytesAvailable:
if (aStream == self.inputStream) {
uint8_t buffer[1024];
long len;
while ([self.inputStream hasBytesAvailable]) {
len = [self.inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(#"%#",output);
}
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Nie można połączyć\n");
break;
case NSStreamEventEndEncountered:
break;
default:
break;
}
}
I want to make output variable as global so I can use it in other functions. I want to do this because I'd like to create conditions - everytime when I send request, controller answers me and sends ">" symbol so that means it is ready to take another request. I want to create condition that will send only when ">" appears. I have already done RegExp for this but now I have problem with access to output variable outside stream function.
When you declaring something as extern you are telling the compiler the type AND that you will define it somewhere else. In your case you never define your variable.
First, ensure it is defined:
// in .h you would have:
extern NSString* const output; // << declaration
// in .m you would have:
NSString * const output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; // << definition
Experts:
I've been researching all morning on how to write an image file to another computer via IP Address. Do I really need to create sockets, set delegates, schedule a run loop, check space available, and all that hoopla? Really? Can't I just save the file to a URL using the IP Address and default port?
I'm asking this question because I'm not making much progress on my own and I know the minute I hit Post Your Question I'll find some useful information. But in case that does not happen, please reply. Any help is appreciated.
This is the code I have and I think I'm on the wrong track:
#import "TESTtcpController.h"
#interface TESTtcpController()
#property (nonatomic, strong)NSInputStream *inputStream;
#property (nonatomic, strong)NSOutputStream *outputStream;
//void CFStreamCreatePairWithSocketToHost (
// CFAllocatorRef alloc,
// CFStringRef host,
// UInt32 port,
// CFReadStreamRef *readStream,
// CFWriteStreamRef *writeStream
// );
#end
#implementation TESTtcpController
+ (void)sendFile:(UIImage *)image
{
UInt32 port = 80;
NSString *ipAddress = #"10.10.10.10";
TESTtcpController *tcpController = [[TESTtcpController alloc] init];
[tcpController connect:port ipAddress:ipAddress];
[tcpController postFile:image];
[tcpController disconnect];
tcpController = nil;
}
-(void)connect:(UInt32)port ipAddress:(NSString *)ipAddress
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ipAddress, port, &readStream, &writeStream);
self.inputStream = (__bridge NSInputStream *)readStream;
self.outputStream = (__bridge NSOutputStream *)writeStream;
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
NSLog(#"input stream id %#", self.inputStream);
/* Store a reference to the input and output streams so that
they don't go away.... */
}
- (void)postFile:(UIImage *)image
{
}
- (void)dataSending:(NSString*)data {
if(self.outputStream) {
if(![self.outputStream hasSpaceAvailable])
return;
NSData *_data=[data dataUsingEncoding:NSUTF8StringEncoding]; int data_len = [_data length];
uint8_t *readBytes = (uint8_t *)[_data bytes];
int byteIndex=0;
unsigned int len=0;
while (TRUE) {
len = ((data_len - byteIndex >= 40960) ? 40960 : (data_len-byteIndex));
if(len==0)
break;
uint8_t buf[len]; (void)memcpy(buf, readBytes, len);
len = [self.outputStream write:(const uint8_t *)buf maxLength:len]; byteIndex += len;
readBytes += len; }
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
switch(eventCode) {
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
break;
case NSStreamEventHasBytesAvailable:
break;
case NSStreamEventHasSpaceAvailable:
// {
// uint8_t *readBytes = (uint8_t *)[_data mutableBytes];
// readBytes += byteIndex; // instance variable to move pointer
// int data_len = [_data length];
// unsigned int len = ((data_len - byteIndex >= 1024) ?
// 1024 : (data_len-byteIndex));
// uint8_t buf[len];
// (void)memcpy(buf, readBytes, len);
// len = [stream write:(const uint8_t *)buf maxLength:len];
// byteIndex += len;
// break;
// }
case NSStreamEventErrorOccurred:
break;
case NSStreamEventEndEncountered:
break;
// continued ...
}
}
-(void)disconnect{
NSLog(#"disconnect method called");
NSStreamStatus socketStatus = [self.outputStream streamStatus];
int status = socketStatus;
NSLog(#"Stream Status is %i", status);
if (status == 2) {
[self.inputStream close];
[self.outputStream close];
NSLog(#"Socket Closed");
}
}
- (void)deallocMe
{
[TESTtcpController dealloc];
}
#end
You should use the AFNetworking library. Image uploads will be trivial. Read about AFNetworking here: http://cocoadocs.org/docsets/AFNetworking/2.0.0/
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:#"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
NSLog(#"Success: %# %#", response, responseObject);
}
}];
[uploadTask resume];
i am succesfully getting data from my server. and after getting it i send the data to the function to parse;
- (void)readIn:(NSMutableData *)s {
NSLog(#"Reading in the following:");
NSString * prints = [[NSString alloc] initWithData:s encoding:NSUTF8StringEncoding];
NSLog(#"%#", prints);
NSError *error = nil;
NSData *jsonData = [[NSData alloc] initWithData:s];
if (jsonData) {
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
if ([jsonObjects isKindOfClass: [NSArray class]])
NSLog(#"yes we got an Array");
else if ([jsonObjects isKindOfClass: [NSDictionary class]])
NSLog(#"yes we got an dictionary");
else
NSLog(#"neither array nor dictionary!");
if (error) {
NSLog(#"error is %#", [error localizedDescription]);
return;
}
NSArray *keys = [jsonObjects allKeys];
for (NSString *key in keys) {
NSLog(#"%# is %#",key, [jsonObjects objectForKey:key]);
}
} else {
// Handle Error
}
}
now my print on console is:
2012-08-17 13:59:57.667 TaraftarlikOyunu[1157:c07] Reading in the following:
2012-08-17 13:59:57.667 TaraftarlikOyunu[1157:c07] {"uID":"5878341","tm":"fb","hh":122,"pt":75,"coin":500,"ll":1,"qlevel":1,"coect":true,"potWeekly":{"pts":75,"intval":604800000},"acent":{"chamunt":0},"mes":[]}
2012-08-17 13:59:57.668 TaraftarlikOyunu[1157:c07] neither array nor dictionary!
2012-08-17 13:59:57.670 TaraftarlikOyunu[1157:c07] error is The operation couldn’t be completed. (Cocoa error 3840.)
it seems legal json object to me. where am i doing wrong?
i am getting data from the server with nsstream; and here is my code to get data:
case NSStreamEventHasBytesAvailable: {
if(stream == inputStream) {
NSLog(#"inputStream is ready.");
uint8_t buf[1024];
unsigned int len = 0;
len = [inputStream read:buf maxLength:1024];
NSLog(#"length %i", len);
if(len > 0) {
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
[data appendBytes: (const void *)buf length:len];
[self readIn:data];
}
}
break;
}
Try explicitly setting the jsonObjects to be an array:
NSError *myError = nil;
NSArray *jsonObjects= [NSJSONSerialization JSONObjectWithData:responseData ptions:NSJSONReadingMutableLeaves error:&myError];
for (NSDictionary * dict in jsonObjects) {
NSLog(#"Some data %#", [dict objectForKey:#"field"]);
//replace this to access a valid field
}
The reason for the failure is that the original data probably has some '\' characters in it quoting '"' characters. If you had searched on "Cocoa error 3840" you would have gotten a hint on this. What I suggest you do is print out the original data, one character at a time (its ascii so no need for UTF) and verify this.
char *ptr = [s bytes];
for(int i=0; i<[s length]; ++i) NSLog(#"%c ", *ptr++);
problem is that, json string i get is coming with null termination at the end and when i try to deserialize it it can not be converted to NSDictionary or NSArray. making a little change on the code makes everything perfect. the true code should be like that
case NSStreamEventHasBytesAvailable: {
if(stream == inputStream) {
NSLog(#"inputStream is ready.");
uint8_t buf[1024];
unsigned int len = 0;
len = [inputStream read:buf maxLength:1024];
NSLog(#"length %i", len);
if(len > 0) {
datum =[[NSMutableData alloc] initWithLength:0];
[datum appendBytes: (const void *)buf length:len-1];
NSDictionary * jsondict = [NSJSONSerialization JSONObjectWithData:datum options:NSUTF8StringEncoding error:nil];
NSLog(#"is valid json object %d",[NSJSONSerialization isValidJSONObject:jsondict]);
[self readIn:datum];
}
}
else {
NSLog(#"no buffer!");
}
break;
}
default: {
NSLog(#"Stream is sending an Event: %i", event);
break;
}
}
only difference from the other one is i threw the last byte and it became valid json dictionary.
thanks for the people who are interested in my question.
JSON doesn't accept any control characters other than tab, form feed, carriage return, and line feed in a JSON document, so your code works perfectly fine and does exactly what it is supposed to do by not reading anything.
So where does that nul character come from? Either your code reading the data is wrong, or the server is wrong. Looks to me like the problem is the server. Your "fix" by throwing away the last character is bad - if the server is ever fixed, you'll throw away the closing brace. I'd contact whoever is responsible for the server and fix the problem there.
I'm trying to send json object to server. But I received an error and I can't fix it.
-(void) connectToHost{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 9123, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open]; }
This is my connection to host.
NSDictionary *setUser = [NSDictionary
dictionaryWithObjectsAndKeys:[#"u" stringByAppendingString:my.id],#"id",
#"GET_USER_INFO",#"command",
#"",#"value",
nil];
NSArray *array = [NSArray arrayWithObject:setUser];
jsonDataToSendTheServer = [array JSONRepresentation];
NSLog(#" %# ", jsonDataToSendTheServer);
// array = [NSArray arrayWithObject:jsonDataToSendTheServer];
NSLog(#" %# ", array);
NSLog(#"true or false %c",[NSJSONSerialization
isValidJSONObject: array]);
bytesWritten = [NSJSONSerialization writeJSONObject:array toStream:outputStream options:NSJSONWritingPrettyPrinted error:nil];
and this part is NSJSONSerialization part.
However I got an error.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '***+[NSJSONSerialization writeJSONObject:toStream:options:error:]: stream is not open for writing'
I'm new at objective-c. I can't fix the problem for 3 hours.
=======================================
edit:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
NSLog(#"stream event %i", streamEvent); //this doesn't post in the log when stream opened...
NSLog(#"bytes %i",bytesWritten);
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[1024];
int len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding];
if (nil != output) {
NSLog(#"server said: %#", output);
//[self messageReceived:output];
}
}
}
}
break;
case NSStreamEventEndEncountered:
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//[theStream release];
theStream = nil;
break;
case NSStreamEventHasSpaceAvailable:
{
uint8_t *readBytes = (uint8_t *)[_data mutableBytes];
readBytes += bytesWritten; // instance variable to move pointer
int data_len = [_data length];
unsigned int len = ((data_len - bytesWritten >= 1024) ?
1024 : (data_len-bytesWritten));
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
//len = [theStream write:(const uint8_t *)buf maxLength:len];
NSLog(#"written %s", buf );
bytesWritten += len;
}
break;
case NSStreamEventErrorOccurred:
{
NSLog(#"no connection");
}
case NSStreamEventNone:
{
//printf("EVENT: None.\n");
break;
}
default:
NSLog(#"Unknown event");
}}
this is my stream: handleEvent: function.
Now after I did add the connectionToHost to delegate I get this kind of error.
012-08-10 16:14:27.302 TaraftarlikOyunu[2274:c07] written P∏◊P‡ˇø
2012-08-10 16:14:28.399 TaraftarlikOyunu[2274:c07] benim bu id 587127341
2012-08-10 16:14:28.399 TaraftarlikOyunu[2274:c07] benim ad Ahmet
2012-08-10 16:14:28.400 TaraftarlikOyunu[2274:c07]
[{"id":"u581277341","command":"GET_USER_INFO","value":""}]
2012-08-10 16:14:28.404 TaraftarlikOyunu[2274:c07] stream event 4
2012-08-10 16:14:28.404 TaraftarlikOyunu[2274:c07] bytes 86
(lldb)
now I don't have an idea that if it buffered or not
=======================EDIT2===============
sorry about this.
the problem probably appears because of this
(void)memcpy(buf, readBytes, len);
I just copy and paste this part of code.
what may be the problem!
The connection method you are using is a little much.
You need to make sure the connection has happened in the delegate
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventHasSpaceAvailable:
NSLog(#\"None!\");
break;
case NSStreamEventOpenCompleted:
NSLog(#\"Stream opened\");
//NOW you can write to the stream
I press the button to connect to the server (TCP), but i don't know whether it connected or not..
Here is that part of the code:
[self connectToServerUsingCFStream:msg portNo:50000];
if(readStream && writeStream)
{
NSString *newText = [[NSString alloc] initWithFormat:#"Connected!! :)"];
statusText.text = newText;
[newText release];
pingButton.hidden = NO;
}
else
{
NSString *newText = [[NSString alloc] initWithFormat:#"Connection unsuccessful :("];
statusText.text = newText;
[newText release];
}
I always get the "Connected!! :)" even if the server is offline :s
The solution for people following the connection method:
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef) urlStr,
portNo,
&readStream,
&writeStream);
if (readStream && writeStream)
{
CFReadStreamSetProperty(readStream,
kCFStreamPropertyShouldCloseNativeSocket,
kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream,
kCFStreamPropertyShouldCloseNativeSocket,
kCFBooleanTrue);
iStream = (NSInputStream *)readStream;
[iStream retain];
[iStream setDelegate:self];
[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[iStream open];
oStream = (NSOutputStream *)writeStream;
[oStream retain];
[oStream setDelegate:self];
[oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[oStream open];
}
is using the
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
like this:
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
NSString *io;
if (theStream == iStream) io = #">>";
else io = #"<<";
NSString *event;
switch (streamEvent)
{
case NSStreamEventNone:
event = #"NSStreamEventNone";
statusText.text = #"Can not connect to the host!";
break;
case NSStreamEventOpenCompleted:
event = #"NSStreamEventOpenCompleted";
pingButton.hidden = NO;
statusText.text = #"Connected";
break;
case NSStreamEventHasBytesAvailable:
event = #"NSStreamEventHasBytesAvailable";
if (theStream == iStream)
{
//read data
uint8_t buffer[1024];
int len;
while ([iStream hasBytesAvailable])
{
len = [iStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
NSData *theData = [[NSData alloc] initWithBytes:buffer length:len];
if (nil != output)
{
//do something with data
}
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
event = #"NSStreamEventHasSpaceAvailable";
if (theStream == oStream)
{
//send data
uint8_t buffer[11] = "I send this";
int len;
len = [oStream write:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSLog(#"Command send");
[oStream close];
}
}
break;
case NSStreamEventErrorOccurred:
event = #"NSStreamEventErrorOccurred";
statusText.text = #"Can not connect to the host!";
pingButton.hidden = YES;
break;
case NSStreamEventEndEncountered:
event = #"NSStreamEventEndEncountered";
statusText.text = #"Connection closed by the server.";
pingButton.hidden = YES;
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[theStream release];
theStream = nil;
break;
default:
event = #"** Unknown";
}
NSLog(#"%# : %#", io, event);
}
(for all I know!) The credits go to deksa from this post (though i don't know who was the creator, because i've seen this some times on the web, including here o SO). This code was slightly modified by me (pingButton, statusText), if you want the original one go to the link previously mentioned.
The Apple Developer Site has some info on this as well.
Like i've said, I had seen some stuff looking like this on the web, but now i understand that everything that happens after you connect is "automatic"; for instance, if the server is on hold with a read(), the case NSStreamEventHasSpaceAvailable: will be called automatically, and all the code in there will be run.
Now I consider this question answered.
Although you did not provide enough informations, I'd suggest to use ASIHTTPRequest for HTTP, and AsyncSocket for TCP and UDP. If an connection was established, callback methods will be triggered,
I have to say, that my experiences with CFNetwork are very limited, but for me it seems, as if you are just testing, if stream objects exists (if(readStream && writeStream)).
A quick look at CFNetwork Programming Guide: Working with Read Streams tells me, that you have to open it with CFReadStreamOpen(), this function will return an boolean, if it really did open the stream.
if (!CFReadStreamOpen(myReadStream)) {
CFStreamError myErr = CFReadStreamGetError(myReadStream);
// An error has occurred.
if (myErr.domain == kCFStreamErrorDomainPOSIX) {
// Interpret myErr.error as a UNIX errno.
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
// Interpret myErr.error as a MacOS error code.
OSStatus macError = (OSStatus)myErr.error;
// Check other error domains.
}
}
BTW:
instead of
NSString *newText = [[NSString alloc] initWithFormat:#"Connected!! :)"];
statusText.text = newText;
[newText release];
you just can write statusText.text = #"Connected!! :)";