Skip to content

Instantly share code, notes, and snippets.

@rjungemann
Created June 21, 2010 00:45
Show Gist options
  • Star 53 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save rjungemann/446256 to your computer and use it in GitHub Desktop.
Save rjungemann/446256 to your computer and use it in GitHub Desktop.
How to open a TCP socket in Objective-C
#import <Foundation/Foundation.h>
@interface Communicator : NSObject <NSStreamDelegate> {
@public
NSString *host;
int port;
}
- (void)setup;
- (void)open;
- (void)close;
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event;
- (void)readIn:(NSString *)s;
- (void)writeOut:(NSString *)s;
@end
#import "Communicator.h"
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
NSInputStream *inputStream;
NSOutputStream *outputStream;
@implementation Communicator
- (void)setup {
NSURL *url = [NSURL URLWithString:host];
NSLog(@"Setting up connection to %@ : %i", [url absoluteString], port);
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)[url host], port, &readStream, &writeStream);
if(!CFWriteStreamOpen(writeStream)) {
NSLog(@"Error, writeStream not open");
return;
}
[self open];
NSLog(@"Status of outputStream: %i", [outputStream streamStatus]);
return;
}
- (void)open {
NSLog(@"Opening streams.");
inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;
[inputStream retain];
[outputStream retain];
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
}
- (void)close {
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 release];
[outputStream release];
inputStream = nil;
outputStream = nil;
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
NSLog(@"Stream triggered.");
switch(event) {
case NSStreamEventHasSpaceAvailable: {
if(stream == outputStream) {
NSLog(@"outputStream is ready.");
}
break;
}
case NSStreamEventHasBytesAvailable: {
if(stream == inputStream) {
NSLog(@"inputStream is ready.");
uint8_t buf[1024];
unsigned int len = 0;
len = [inputStream read:buf maxLength:1024];
if(len > 0) {
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
[data appendBytes: (const void *)buf length:len];
NSString *s = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self readIn:s];
[data release];
}
}
break;
}
default: {
NSLog(@"Stream is sending an Event: %i", event);
break;
}
}
}
- (void)readIn:(NSString *)s {
NSLog(@"Reading in the following:");
NSLog(@"%@", s);
}
- (void)writeOut:(NSString *)s {
uint8_t *buf = (uint8_t *)[s UTF8String];
[outputStream write:buf maxLength:strlen((char *)buf)];
NSLog(@"Writing out the following:");
NSLog(@"%@", s);
}
@end
#import <Foundation/Foundation.h>
#import "Communicator.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Communicator *c = [[Communicator alloc] init];
c->host = @"http://127.0.0.1";
c->port = 6789;
[c setup];
[c open];
[pool drain];
return 0;
}
@metuceng
Copy link

thanks for the code. but i got an error while running. i tried to write something to outputstream but it says "stream is not open for writing".
at the same time i checked the streamstatus and it returns 0. why could it be

@abusivewings
Copy link

How do i receive data?

@trfd
Copy link

trfd commented May 22, 2013

I have quite the same implementation as yours on my iOS app, but the messages written in the output stream are sent to my server only when the app is killed (stopped by xcode or killed in the iOS dock).
Are your messages sent right after the write:maxLength: call ?

Edit: Problem solved, apparently the message must finish with a "\n" to flush the output stream !

@CraigMetcalfe
Copy link

@traff589: sometimes I believe it requires "\r\n", that is just to be extra safe in case newline by itself is not working.

Anyhow, if your project uses ARC, just remove references to [retain] and [release], along with NSAutoReleasePool

@AshrafTawfeeq
Copy link

Craig's answer did all the magic.

@jp-dubey07
Copy link

I'm getting error : Cast of objective-C pointer type 'NSString' to C pointer type 'CFStringtRef'(aka 'const struct_CFString *') requires a bridged cast.
What should be fix?

@jp-dubey07
Copy link

Also, I want to sent dictionary along with request while opening the socket. Based on dictionary content I should get response from server. In Java below code is used :

printWriter.println("search^"+ asNoOfRecords + "|5|"+ asReturnType +"|" + asPageNo + "^" + asSearchCriteria + "^1234567abcdefg");

What changes need to be carried out in code to implement this?

@hafiz-mohsin-confiz
Copy link

how to communicate the client with server ?
can give some demo about client its helps alot people.

@axelpanning
Copy link

For me the (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event is never called. I used exactly the files you put here. I can write data to a server but i never get response. I encountered several people in the web have similar issues with that event and receiving data.

What can I do wrong here?

@dkressaty
Copy link

Axelpanning: In recent versions of iOS Apple has started rigidly enforcing privacy and permissions. And, here's the real rub, calls to services have been known to die silently, without throwing an error. Makes it tough to troubleshoot. It took me nearly a week to find out that my calls to Location Services were being ignored. Most likely there's a key that you'll need to add to the info.plist file AND make a call to iOS to ask the user for permission to access network services or some such thing. As I work through this example, if I find the exact combination, I'll post it here.

@yuktikapahwa
Copy link

Hi,
I am able to open a stream with the server ,but how can i write a message in the output stream ?
I am sorry but I am completely new to objective C.
Any help would be appreciated
I want to write any message-May be "hello World"

@nareshpareek
Copy link

hi @rjungemann
Thank you for simple code. Could you help me write something similar in Swift 3.0

@krunal13257
Copy link

Amazing example works well.... I am able to send data to other device but when i write to output stream data is getting received on other side when i close my app, please help what could be the mistake?

@bibinmathew3720
Copy link

Not able to send data in ios 11

@vikrantrajput
Copy link

Code is working well means I am getting streaming data in handleEvent delegate method but when app is in foreground mean when I lock my iPhone the connection getting break TCP connection break. So how I can handle this problem. I got stuck on this point.
Thanks

@omy2301
Copy link

omy2301 commented Feb 23, 2018

[data appendBytes: (const void *)buf length:len];

I got crash here

@limtingfei
Copy link

For those who successfully streamed, what is the suitable stream and event argument to pass in in order to start Listening?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment