I want to display an PNG-image I get via binary stream when I send a nullbyte to the server.
I do get information from the stream. But the image is never shown and I don't know why. Maybe someone sees a mistake.
My code is following:
#import <UIKit/UIKit.h>
NSInputStream *inputStream;
NSOutputStream *outputStream;
#interface ViewController : UIViewController <NSStreamDelegate>
#property (weak, nonatomic) IBOutlet UIView *secondView;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)sendNullbyte:(id)sender;
#property (weak, nonatomic) IBOutlet UIView *firstView;
#property (nonatomic, strong, readwrite) NSOutputStream *fileStream;
#end
and
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initNetworkCommunication];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 80, &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];
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent{
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
NSLog(#"Has bytes available.");
//be sure that event comes from input stream
if(theStream == inputStream){
UInt8 buffer[500000];
long len;
BOOL firstbytes = true;
//read method returns 0 when there is nothing left in the stream
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0){
NSData *output = [[NSData alloc] initWithBytes:buffer length:len-4];
if (output != nil){
NSLog(#"server said: %#", output);
UIImage *image = [[UIImage alloc] initWithData:output];;
_imageView.image = image;
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Cant not connect to the host");
break;
case NSStreamEventEndEncountered:
break;
default:
break;
}
}
- (IBAction)sendNullbyte:(id)sender {
NSInteger nullbyte = 0x00;
NSData *data =[[NSData alloc] initWithBytes:&nullbyte length:1];
[outputStream write:[data bytes] maxLength:[data length]];
[self.view bringSubviewToFront:_secondView];
}
#end
Try to use unit8_t instead UInt8, and make sure that u handle the case that the image doesn't get to u in a single packet...
U can do something like this:
{
NSMutableData *data; // ivar
}
// init it somewhere
data = [NSMutableData new];
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[5000];
int length;
while ([inputStream hasBytesAvailable]) {
length = [inputStream read:buffer maxLength:sizeof(buffer)];
if (length > 0) {
[data appendBytes:(const void *)buffer length];
}
}
}
break;
case NSStreamEventEndEncountered:
{
if (theStream == inputStream) {
UIImage *imagess = [[UIImage alloc]initWithData:data];
[imagesview setImage:imagess];
}
} break;
Related
I have successfully created connection to Apple MFi printer, but I'm failed to have NSOutputStream to write to the printer because delegate did not called.
Here is my LibPrint.h:-
#import <Foundation/Foundation.h>
#import <ExternalAccessory/ExternalAccessory.h>
#import "FlashRuntimeExtensions.h"
#interface LibPrint : NSObject <NSStreamDelegate>
- (void)printR;
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent;
#end
// C interface
FREObject fncPrintR(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
LibPrint.m:-
#import "LibPrint.h"
#interface LibPrint ()
#property (nonatomic, strong) EASession *easPrinter;
#property (nonatomic, strong) NSData *datPrintData;
#end
#implementation LibPrint
FREContext eventContext;
LibPrint *AirInAppRefToSelf;
#pragma mark - NSObject
-(id)init
{
self = [super init];
if (self)
{
AirInAppRefToSelf = self;
self.easPrinter = nil;
self.datPrintData = nil;
}
return self;
}
-(void)dealloc
{
self.easPrinter = nil;
self.datPrintData = nil;
AirInAppRefToSelf = nil;
}
#pragma mark - ANE setup
void LibPrintExtContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet)
{
*numFunctionsToTest = 1;
FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest);
func[0].name = (const uint8_t*) "printR";
func[0].functionData = NULL;
func[0].function = &fncPrintR;
*functionsToSet = func;
eventContext = ctx;
if ((LibPrint*) AirInAppRefToSelf == nil)
{
AirInAppRefToSelf = [[LibPrint alloc] init];
}
}
void LibPrintContextFinalizer(FREContext ctx) { }
void LibPrintExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet)
{
*extDataToSet = NULL;
*ctxInitializerToSet = &LibPrintExtContextInitializer;
*ctxFinalizerToSet = &LibPrintContextFinalizer;
}
void LibPrintFinalizer(void* extData) { }
#pragma mark - C interface
FREObject fncPrintR(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
FREObject result = NULL;
if ([AirInAppRefToSelf datPrintData] != nil) {
[AirInAppRefToSelf setDatPrintData:nil];
}
// Retrieve message
NSData *ldatPrintData = toNSDataByteArray(argv[0]);
[AirInAppRefToSelf setDatPrintData:ldatPrintData];
[(LibPrint*) AirInAppRefToSelf printR];
return result;
}
- (void)printR
{
BOOL lblnConnected = false;
BOOL lblnFound = false;
NSArray *accessories = [EAAccessoryManager sharedAccessoryManager].connectedAccessories;
for (EAAccessory *accessory in accessories)
{
if (accessory.connected)
{
lblnConnected = true;
for (NSString *protocol in accessory.protocolStrings)
{
if ([protocol isEqualToString:#"jp.star-m.starpro"])
{
lblnFound = true;
[self setEasPrinter:[[EASession alloc] initWithAccessory:accessory forProtocol:protocol]];
[[self easPrinter].outputStream setDelegate:self];
[[self easPrinter].outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[self easPrinter].outputStream open];
}
}
}
}
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"connected: %s", lblnConnected ? "true" : "false"] UTF8String]);
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"found: %s", lblnFound ? "true" : "false"] UTF8String]);
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [#"NSStreamDelegate" UTF8String]);
switch (streamEvent)
{
case NSStreamEventNone:
{
break;
}
case NSStreamEventOpenCompleted:
{
break;
}
case NSStreamEventHasBytesAvailable:
{
break;
}
case NSStreamEventHasSpaceAvailable:
{
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [#"NSStreamEventHasSpaceAvailable" UTF8String]);
NSInteger len = [[self easPrinter].outputStream write:[[self datPrintData] bytes] maxLength:[[self datPrintData] length]];
FREDispatchStatusEventAsync(eventContext, (uint8_t*)"DEBUG_DATA", (uint8_t*) [[NSString stringWithFormat: #"data len: %ld, returned len: %ld", [[self datPrintData] length], len] UTF8String]);
break;
}
case NSStreamEventErrorOccurred:
{
break;
}
case NSStreamEventEndEncountered:
{
break;
}
}
}
NSData *toNSDataByteArray(FREObject *ba)
{
FREByteArray byteArray;
FREAcquireByteArray(ba, &byteArray);
NSData *d = [NSData dataWithBytes:(void *)byteArray.bytes length:(NSUInteger)byteArray.length];
FREReleaseByteArray(ba);
return d;
}
#end
I have printer connected good, but the delegate method [- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent] never run. I guess maybe
the currentRunLoop issue, I tried to change it to mainRunLoop, but still no clue. Please help! Thx in advanced.
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Instead of using [NSRunLoop currentRunLoop] I changed it to [NSRunLoop mainRunLoop].
set inputStrean in the same way:
[[self easPrinter].inputStream setDelegate:self];
[[self easPrinter].inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[[self easPrinter].inputStream open];
I have this sample code taken from the example of this iPhone chat server.
In my case I need to send larger amounts of data, 100k-200k thus I changed the buffer size to something that can accommodate what I want.
On the iOS simulator (emulating a 6plus) everything works perfectly, as soon as I try to debug on my iPhone 6plus after implementing the suggestions of #tc. I get the incoming message broken into 3-4 parts! Any ideas?
2015-02-03 22:42:34.756 Sock1[7390:3773054] Incoming message: XML part 1
2015-02-03 22:42:34.759 Sock1[7390:3773054] Incoming message: XML part 2
2015-02-03 22:42:34.774 Sock1[7390:3773054] Incoming message: XML part 3
2015-02-03 22:42:34.794 Sock1[7390:3773054] Incoming message: XML part 4
XML part 1-4 make up the entire message that should have been in one as there is no null byte character within.
Just to make things even stranger, when I add a break point on this line:
[currentMessage appendBytes:buffer length:len];
and go through step by step (69-70 pressing Continue) everything works fine! No errors at all! So it is something to do with the speed of parsing or receiving or something I can't figure out?
What I've made sure is that the server doesn't send any null byte characters apart from the terminating one at the end of the message.
The code I use is this:
#implementation ViewController
bool connectionError = true;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)#"192.168.1.1", 6035, &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];
}
- (void)closeAll {
NSLog(#"Closing streams.");
[inputStream close];
[outputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream setDelegate:nil];
[outputStream setDelegate:nil];
inputStream = nil;
outputStream = nil;
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
connectionError = false;
if (theStream == inputStream) {
uint8_t buffer[1024];
long len;
NSMutableData *currentMessage;
currentMessage = [NSMutableData dataWithBytes:"" length:strlen("")];
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
[currentMessage appendBytes:buffer length:len];
}
NSString *newMessage = [[NSString alloc] initWithData:currentMessage encoding:NSUTF8StringEncoding];
NSLog(#"Incoming message: %#",newMessage);
NSData *nullByte = [NSMutableData dataWithLength:1];
len = currentMessage.length;
NSRange searchRange = {0, len};
for (NSRange r; (r = [currentMessage rangeOfData:nullByte options:0 range:searchRange]).length; ) {
NSString *message = [[NSString alloc] initWithBytes:currentMessage.bytes length:r.location encoding:NSUTF8StringEncoding];
searchRange.location = r.location+r.length;
searchRange.length = len - searchRange.location;
[self messageReceived:message];
}
[currentMessage replaceBytesInRange:(NSRange){0, searchRange.location} withBytes:NULL length:0];
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can not connect to the host!");
connectionError = true;
[self closeAll];
[self connectionLost];
break;
case NSStreamEventEndEncountered:
break;
default:
NSLog(#"Unknown event");
}
}
- (void) connectionLost {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert!"
message:#"Connection to the server lost!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
- (void) messageReceived:(NSString *)message {
[messages addObject:message];
if (inputStream.streamStatus == NSStreamStatusClosed || inputStream.streamStatus == NSStreamStatusError || inputStream.streamStatus == NSStreamStatusNotOpen) {
[self closeAll];
[self initNetworkCommunication];
}
// do things with the message, XML parsing...
}
- (void) initConnection {
[self initNetworkCommunication];
messages = [[NSMutableArray alloc] init];
}
- (IBAction)joinChat:(id)sender {
[self initConnection];
[self sendSocketMessage: #"iam:" message: _inputNameField.text];
}
- (void) sendSocketMessage:(NSString*) sendCommand message:(NSString*) sendMessage
{
// do something...
if (outputStream.streamStatus == NSStreamStatusClosed || outputStream.streamStatus == NSStreamStatusError || outputStream.streamStatus == NSStreamStatusNotOpen) {
[self closeAll];
[self initNetworkCommunication];
}
NSString *response = [NSString stringWithFormat: #"%#%#", sendCommand, sendMessage];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
NSLog(#"clint sent: %#", response);
}
#end
The short answer is that TCP offers a stream of bytes, not a stream of variable-length messages¹. I don't know why it works in the simulator, unless 192.168.1.1 is the same machine (in which case it isn't subject to the usual flow control, though it's perhaps surprising that the kernel buffers are that big).
To work around this, you need to somehow signal where the end of a message is. There are two common ways:
Length-prefixes. Examples include DJB's netstrings (e.g. 5:abcde for the bytestring "abcde"), HTTP's Content-Length, HTTP 1.1's chunked encoding, and various binary protocols typically with 8-bit, 16-bit, or variable-length-encoded lengths.
Delimiters. Examples include newlines (traditionally CRLF, e.g. in Telnet/SMTP/HTTP/IRC), null bytes, MIME boundaries (ick).
In this case, we can make use of the fact that null bytes aren't permitted within XML. currentMessage is assumed to be a NSMutableData ivar and not nil.
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
[currentMessage appendBytes:buffer length:len];
}
NSData * nullByte = [NSMutableData dataWithLength:1];
len = currentMessage.length;
NSRange searchRange = {0, len};
for (NSRange r; (r = [currentMessage rangeOfData:nullByte options:0 range:searchRange]).length; ) {
NSString * message = [[NSString alloc] initWithBytes:currentMessage.bytes length:r.location encoding:NSUTF8StringEncoding];
searchRange.location = r.location+r.length;
searchRange.length = len - searchRange.location;
[self messageReceived:message];
}
[currentMessage replaceBytesInRange:(NSRange){0, searchRange.location} withBytes:NULL length:0];
Also note that initializing things in -viewDidLoad requires some care if the view can be unloaded (this is less of an issue if you only support iOS 6+, since views are no longer automatically unloaded).
I'm trying to send an image to the twisted server and back to my iPhone. My code works on the simulator but does not work on the iPhone. I have no idea why. All I'm doing is sending the data for the image to the server and then immediately back to my iPhone. Here is the relevant code that I'm using.
SERVER SIDE:
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
class IphoneChat(Protocol):
def connectionMade(self):
#self.transport.write("""connected""")
self.factory.clients.append(self)
print "clients are ", self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
def dataReceived(self, data):
#print "data is ", data
self.transport.write(data);
def message(self, message):
self.transport.write(message + '\n')
factory = Factory()
factory.protocol = IphoneChat
factory.clients = []
reactor.listenTCP(80, factory)
print "Server Started"
reactor.run()
CLIENT SIDE:
#interface LoginScreen : UIViewController <NSStreamDelegate> {
}
#property (strong, nonatomic) NSMutableData *outputData;
#property (strong, nonatomic) IBOutlet UIImageView *testImage;
#implementation LoginScreen : UIViewController
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"avis-mbp", 80, &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];
}
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[1024];
long len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSData *output = [[NSData alloc] initWithBytes:buffer length:len];
if (nil != output) {
[self.appDel.outputData appendBytes:buffer length:len];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can not connect to the host!");
break;
case NSStreamEventEndEncountered:
NSLog(#"Event Ended");
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
default:
break;
}
}
-(IBAction)runNetworkingTest:(id)sender {
[self initNetworkCommunication];
NSData *pictureData = UIImagePNGRepresentation([UIImage imageNamed:#"shalin.jpg"]);
NSMutableData *mutedData = [[NSMutableData alloc] initWithData:pictureData];
[outputStream write:[mutedData bytes] maxLength:[mutedData length]];
}
-(IBAction)testPicture:(id)sender {
UIImage *image = [UIImage imageWithData:self.outputData];
self.testImage.image = image
}
I found the solution to my problem. It had to do with the space available when writing to the server. The iPhone can only write a specific amount of bytes at a time, so I had to regulate the amount of data that was written in the delegate via the NSStreamEventHasSpaceAvailable case. Here is the missing piece of code that will allow you to write an image to the server and read it back to the client via a TCP connection to a twisted server:
Missing Code to be put in the NSStream Delegate
case NSStreamEventHasSpaceAvailable:
{
if (self.appDel.willWrite && [self.appDel.inputData length] != 0) {
int bufferSize = 1024;
if ([self.appDel.inputData length] > bufferSize){
NSData *sendData = [self.appDel.inputData subdataWithRange:NSMakeRange(0, bufferSize)];
self.appDel.inputData = [[NSMutableData alloc] initWithData:[self.appDel.inputData subdataWithRange:NSMakeRange(bufferSize, [self.appDel.inputData length] - bufferSize)]];
[outputStream write:[sendData bytes] maxLength:[sendData length]];
} else {
[outputStream write:[self.appDel.inputData bytes] maxLength:[self.appDel.inputData length]];
self.appDel.inputData = [[NSMutableData alloc] init];
}
}
}
Modified version of the run networking test
-(IBAction)runNetworkingTest:(id)sender {
[self initNetworkCommunication];
self.appDel.willWrite = YES;
NSData *pictureData = UIImagePNGRepresentation([UIImage imageNamed:#"shalin.jpg"]);
[self.appDel.inputData appendData:pictureData];
}
Code to display the image
-(IBAction)showNetworkingArray:(id)sender {
UIImage *image = [UIImage imageWithData:self.appDel.outputData];
self.testImage.image = image;
}
Notice: I am writing 1024 bytes at a time. IT WILL NOT WORK IF YOU WRITE TOO MANY BYTES AT A TIME. For example, I tried 1024 * 8 and that did not work with a single image. However, when I set the buffer size to be 1024, I was able to send about ten images over without a problem.
I did simple app that connects to tcp stream server(OBD wifi connection in car).
It connects and works pretty well - I can send messages and get answers from car. Now I want to read only specified data from answer. When I send request to car for example 01041 it will answer something like this:
SEARCHING: OK
41 04 7F
I want create a variable that will contain only last bytes of this answer. In this example it will be 7F. I want do this because I'd like to present that data in Label. So I need to skip in this example line Searching and skip first 2 bytes in line 2 to get only 7F. How I can do it?
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (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];
}
- (IBAction)Connect:(id)sender {
[self initNetworkCommunication];
}
- (IBAction)Play:(id)sender {
NSString *response = [NSString stringWithFormat:#"01041\r\n"];
[NSThread sleepForTimeInterval:0.05];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSUTF8StringEncoding]];
}
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted:
[self.logTextView setText:[self.logTextView.text stringByAppendingString:#"Stream opened\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];
//NSString *oborty = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
[self.logTextView setText:[self.logTextView.text stringByAppendingString:output]];
[self.RPM setText:[self.RPM.text stringByAppendingString:output]];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
[self.logTextView setText:[self.logTextView.text stringByAppendingString:#"Can not connect to the host!"]];
break;
case NSStreamEventEndEncountered:
break;
default:
NSLog(#"Unknown event");
}
}
- (IBAction)sendCode:(id)sender {
NSString *command = self.commandTextField.text;
NSString *response = [NSString stringWithFormat:#"%#\r\n", command];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSUTF8StringEncoding]];
[self.outputStream write:[data bytes] maxLength:[data length]];
}
#end
I did that tcp connection with help from tutorial from http://www.raywenderlich.com so I don't understand it that much to solve my problem.
This line [self.RPM setText:[self.RPM.text stringByAppendingString:output]]; shows answer in Label but it shows everything. I think I need to create new variable output and edit it somehow but I don't know how
I am able to connect my iOS program to a java based socket listener and get it connected well. iOS app is also able to send screen shot image data to the socket very well. This is done under NSStreamEventHasSpaceAvailable
My problem is, i do not know, how to send this screenshot image periodically to the socket. I am sending it just once now, its working. But, i want to keep sending this image data to socket one after another screenshot taken programmatically in every certain interval. How to do that? Please advise.
Please refer my complete code below.
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
{
NSString *io;
if (theStream == inputStream) io = #">>";
else io = #"<<";
NSString *event;
switch (streamEvent)
{
case NSStreamEventNone:
event = #"NSStreamEventNone";
//statusText.text = #"Can not connect to the host!";
NSLog(#"NSStreamEventNone - Can not connect to the host");
break;
case NSStreamEventOpenCompleted:
event = #"NSStreamEventOpenCompleted";
//pingButton.hidden = NO;
//statusText.text = #"Connected";
NSLog(#"Connected");
break;
case NSStreamEventHasBytesAvailable:
event = #"NSStreamEventHasBytesAvailable";
NSLog(#"NSStreamEventHasBytesAvailable called");
if (theStream == inputStream)
{
//read data
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];
NSData *theData = [[NSData alloc] initWithBytes:buffer length:len];
if (nil != output)
{
//do something with data
NSLog(#"NSStreamEventHasBytesAvailable theData: %#", theData);
}
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
event = #"NSStreamEventHasSpaceAvailable";
NSLog(#"NSStreamEventHasSpaceAvailable called");
NSLog(#"space : %d",[outputStream hasSpaceAvailable]);
if (theStream == outputStream)
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
UIGraphicsBeginImageContext(appDelegate.window.bounds.size);
[appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:#"screenshot.png" atomically:YES];
int num = [outputStream write:[data bytes] maxLength:[data length]];
if (-1 == num) {
NSLog(#"Error writing to stream %#: %#", outputStream, [outputStream streamError]);
}else{
NSLog(#"Wrote %i bytes to stream %#.", num, outputStream);
//[outputStream close];
}
}
break;
case NSStreamEventErrorOccurred:
event = #"NSStreamEventErrorOccurred";
//statusText.text = #"Can not connect to the host!";
//pingButton.hidden = YES;
NSLog(#"NSStreamEventErrorOccurred - Can not connect to the host");
break;
case NSStreamEventEndEncountered:
event = #"NSStreamEventEndEncountered";
//statusText.text = #"Connection closed by the server.";
//pingButton.hidden = YES;
NSLog(#"NSStreamEventEndEncountered - Connection closed by the server");
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//[theStream release];
theStream = nil;
break;
default:
event = #"** Unknown";
}
NSLog(#"%# : %#", io, event);
}
Under a Button click, the below code is for connecting the host initially.
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 8080, &readStream, &writeStream);
inputStream = (__bridge_transfer NSInputStream *)readStream;
outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);