Iphone NSStreamDelegate issues connecting to java socket server - iphone

I am trying to open a socket connection from my iphone simulator and send a simple NSString to a localhost server I set up with java in port 80.
The problem that I have is that when I write data on the NSOutputStream its not being received by the server until I close the simulator. And then the server receives the data and this exception is thrown java.net.SocketException: Broken pipe
I know is something related with closing the NSOutputStream and flushing, but how can I achieve this in Objective c?
I call the ProtocolCommunication in my initial ViewController like this:
protocol = [[ProtocolCommunication alloc] init];
[protocol initNetworkCommunication];
[protocol sendData];
ProtocolCommunication class (IOS)
#implementation ProtocolCommunication
#synthesize inputStream, outputStream
- (void) initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 80, &readStream, &writeStream);
inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
//do the Looping
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
NSLog(#"INIT COMPLETE");
}
- (void) sendData {
NSString *response = #"HELLO from my iphone";
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
}
Java Server
String msgReceived;
try {
ServerSocket serverSocket = new ServerSocket(80);
System.out.println("RUNNING SERVER");
while (running) {
Socket connectionSocket = serverSocket.accept();
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
msgReceived = inFromClient.readLine();
System.out.println("Received: " + msgReceived);
outToClient.writeBytes("Aloha from server");
outToClient.flush();
outToClient.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Any Ideas??

I solved it by just adding \n to the NSString like this:
NSString *response = #"HELLO from my iphone \n"; // This flushes the NSOutputStream so becarefull everyone

Related

socket programming in objective c

I have an app that uses socket
In my application , i am trying to establish socket connection and after connecting socket i need to send soap request to server.i'm having problem with soap request sending to server. i have attached the code. Please help me in this
BOOL status;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
urlString = #"hoegamestg.hogaming.info";
// urlString = #"247liveagent.hointeractive.com";
if (![urlString isEqualToString:#""])
{
NSURL *website = [NSURL URLWithString:urlString];
if (!website)
{
NSLog(#"%# is not a valid URL", urlString);
status = NO;
}
else
{
NSLog(#"URL IS VALID%#",website );
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef) [website host], 5654, &readStream, &writeStream);
// CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef) urlString, 5654, &readStream, &writeStream);
//USE TOLL-FREE BRIDGING FOR CONVERTING CORE-FOUNDATION STREAMS TO NSSTREAMS.
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
//SET DELEGATES TO STREAMS.
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
//AVOID BLOCKING OPERATIONS BY SCHEDULING THEM ON TO RUN LOOPS.
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//FINALLY OPEN THE STREAMS.
[self.inputStream open];
[self.outputStream open];
}
}......
Delegate method and soap request
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
// Start Logging events.
// NSString *str = [NSString stringWithFormat:#"%d",eventCode];
// NSMutableString *subscribeTableString;
NSData *data;
NSString *soapMessage = [[NSString alloc]init];
switch (eventCode) {
case NSStreamEventNone:
NSLog(#"NSStreamEventNone");
break;
case NSStreamEventOpenCompleted:
NSLog(#"NSStreamEventOpenCompleted");
break;
case NSStreamEventHasBytesAvailable:
NSLog(#"NSStreamEventHasBytesAvailable");
[self readDataFromStream];
break;
case NSStreamEventHasSpaceAvailable:
NSLog(#"NSStreamEventHasSpaceAvailable");
soapMessage=[soapMessage stringByAppendingString:[NSString stringWithFormat:#"<subscribe channel=\"table-bc7ire5oi4uhetfd\" ><player id=\"%#\" />",socketValue ]];
// soapMessage=[soapMessage stringByAppendingString:[NSString stringWithFormat:#"<subscribe channel=\"table-bc7ire5oi4uhetfd\" ><player id= \"c2da1a80c52542dd\" />" ]];
soapMessage =[soapMessage stringByAppendingString:[NSString stringWithFormat:#"<sessionid id=\"%#\"",socketname]];
soapMessage =[soapMessage stringByAppendingString:[NSString stringWithFormat:#"></sessionid></subscribe>"]];
NSLog(#"THE STRING IS : %#", soapMessage);
data = [[NSData alloc] initWithData:[soapMessage dataUsingEncoding:NSASCIIStringEncoding]];
[self.outputStream write:[data bytes] maxLength:[data length]];
NSLog(#"THE STRING IS : %#", self.outputStream);
[self setMWriteData:[NSData dataWithBytes:(__bridge const void*)soapMessage length:
[soapMessage length]]];
[self writeDataToStream];
// <subscribe channel="table-l8i2hq4jo2hjj9ca"><player id="b82fe3c52020494b" /><sessionid id="246421321cc873d080b550bcc555de0e9d9d29d8cba6f243ec56d38c5785"></sessionid></subscribe>
break;
case NSStreamEventErrorOccurred:
NSLog(#"NSStreamEventErrorOccurred");
NSLog(#"THE ERROR IS : %#", [aStream streamError]);
break;
case NSStreamEventEndEncountered:
break;
default:
break;
}
}
If I'm not mistaken, SOAP is based on the HTTP protocol, so you cannot use raw sockets for that. You can refer to this question if you do need SOAP: how to send/recieve soap object with objective c for ipad
However, if you meant simply sending XML over raw sockets, then you'll need to tell the receiver when to stop reading.
HTTP's way of ending streams is adding \r\n\r\n to the end of the string, so you can use that.
Another way is sending a 4 byte header with the amount of bytes to be sent, so add this (untested):
int s = [data length];
NSData *size = [NSData dataWithBytes:&s length:4];
[self.outputStream write:[size bytes] maxLength:[size length]];
before this
[self.outputStream write:[data bytes] maxLength:[data length]];
The server needs to be aware of this and treat every first 4 bytes as the header, and then reading the amount of bytes mentioned in the header.
I think it would be easier to use HTTP's method with the server stopping its reading when it encounters \r\n\r\n

NSURLConnection sendAsynchronousRequest - communicating with HTTPS

Am working on an iPhone App which fetches an image from a URL. I was using 'NSData dataWithContentsOfUrl] & it worked fine.
But then, as you might have guessed, the request is synchronous.
I want the request to be asynchronous. So, I tried using the NSURLConnection's sendAsynchronousRequest() call. But this returns the following error in the method 'didFailWithError' :
Error Domain=kCFErrorDomainCFNetwork Code=310 "There was a problem
communicating with the secure web proxy server (HTTPS).
Can someone please help?
This is my NSURLConnection code snippet:
NSURL *url = [NSURL URLWithString:notePicUrl];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:100.0];
//NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSURLConnection* _connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:NO];
self.port = [NSPort port];
self.runLoop = [NSRunLoop currentRunLoop];
[self.runLoop addPort:self.port forMode:NSDefaultRunLoopMode];
[_connection scheduleInRunLoop:self.runLoop forMode:NSDefaultRunLoopMode];
[_connection start];
while (self.finished != YES ) {
[self.runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]];
}
[self.runLoop removePort:[self port] forMode:NSDefaultRunLoopMode];
[_connection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
And the NSURLConnectionDelegate methods (not yet implemented ; just testing to first see if it works) ...
-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
NSLog(#"didReceiveResponse");
//_data = [[NSMutableData alloc] init]; // _data being an ivar
}
-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
NSLog(#"didReceiveData");
//[_data appendData:data];
}
-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
NSLog(#"didFailWithError %#", [error description]);
// Handle the error properly
}
-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSLog(#"connectionDidFinishLoading");
//[self handleDownloadedData]; // Deal with the data
}
I just fixed this ; I tried using the simple code line:
[[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
And then handling the data in the Delegate methods. Earlier, it was attempting to run in a separate thread. this works just fine & is asynchronous.

send image or video to a server using socket streaming

I successfully open a socket to send data to it.When i tried to send an image it crashed and when i send string to it it works fine.I am converting an image to data and then put this data into the string that has to be send to server.
Need guidance, please help
Below is the code , i am using to connect with stream.
NSString *urlStr = #"http://182.71.22.107:1935/VideoCalling/5d14a9bc-b816-4c82-bbb7-623d18243a02.sdp/playlist.m3u8";
if (![urlStr isEqualToString:#""])
{
NSURL *website = [NSURL URLWithString:urlStr];
if (!website)
{
NSLog(#"%# is not a valid URL");
return;
}
NSHost *host = [NSHost hostWithName:[website host]];
// iStream and oStream are instance variables
[NSStream getStreamsToHost:host port:8081 inputStream:&iStream outputStream:&oStream];
[iStream retain];
[oStream retain];
[iStream setDelegate:self];
[oStream setDelegate:self];
NSData *data = UIImageJPEGRepresentation([UIImage imageNamed:#"abc.png"], 90);
// Convert from host to network endianness
uint32_t length = (uint32_t)htonl([data length]);
// Don't forget to check the return value of 'write'
[oStream write:(uint8_t *)&length maxLength:4];
[oStream write:[data bytes] maxLength:length];//writes to stream
[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[oStream scheduleInRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];
[iStream open];
[oStream open];
}
Here i write to stream
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
int byteIndex;
switch(eventCode) {
case NSStreamEventHasSpaceAvailable:{
if (stream == oStream) {
//NSString * str = [NSString stringWithFormat:#"sdsdfdfggghhfhfh"];
NSString * str = [[NSString alloc]initWithData:datap encoding:NSUTF16StringEncoding];
NSLog(#"%#,lenght===%d",str,[str length]);
const uint8_t * rawstring = (const uint8_t *)[str UTF8String];
[oStream write:rawstring maxLength:strlen(15)];
[oStream close];
}
UIAlertView *a = [[UIAlertView alloc]initWithTitle:#"h" message:#"Available" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil];
[a show];
[a release];
}
break;
Try this sample by apple developer in PostController

establish socket connection to streaming server and iphone

I want to establish socket connection to streaming server (with iphone ) and want to download its content like image,.css,etc to iphone. Any Idea or sample code is can help me. I need to write code for client only.
Establish Connection as follows and change the urlStr to your server URL
NSString *urlStr = #"http://192.168.0.108";
NSURL *website = [NSURL URLWithString:urlStr];
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);
NSInputStream *inputStream = (NSInputStream *)readStream;
NSOutputStream *outputStream = (NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
Make Use of NSStream Delegate as follows to read data
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
NSLog(#"Bytes Available");
uint8_t b[1024];
unsigned int len = 0;
NSMutableData *data = [[NSMutableData alloc] init];
len = [(NSInputStream *)stream read:b maxLength:1024];
if(!len) {
if ([stream streamStatus] != NSStreamStatusAtEnd)
{
}
} else {
[data appendBytes:(const void *)b length:len];
int bytesRead;
bytesRead += len;
//make use of data here
}
}
break;
}
}
Slightly changes in the code I used:
NSHost *host = [NSHost hostWithName:[website host]];
[NSStream getStreamsToHost:host
port:8766
inputStream:iStream
outputStream:oStream];
Instead of
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);
NSInputStream *inputStream = (NSInputStream *)readStream;
NSOutputStream *outputStream = (NSOutputStream *)writeStream;

Is there anything like 'getStreamsToHost' on real iPhone device?

I want to write an NSOutputStream to a server with apple's sample code:
NSURL *website = [NSURL URLWithString:str_IP];
NSHost *host = [NSHost hostWithName:[website host]];
[NSStream getStreamsToHost:host port:1100 inputStream:nil outputStream:&oStream];
[oStream retain];
[oStream setDelegate:self];
[oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[oStream open];
These codes works well on the iPhone simulator, but when I build it to real device. Two warnings pop up. The problem is:
1)class NSHost doesn't belong to iphone os library
2)getStreamsToHost is not found either
Any suggestions for the alternative method or class which can be used on real device?
Since CFWriteStream is toll-free bridged to NSOutputStream you can use CFStreamCreatePairWithSocketToHost to get your stream pair:
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, port, &readStream, &writeStream);
if (readStream && writeStream) {
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
inputStream = (NSInputStream *)readStream;
[inputStream retain];
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
outputStream = (NSOutputStream *)writeStream;
[outputStream retain];
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
}
if (readStream)
CFRelease(readStream);
if (writeStream)
CFRelease(writeStream);