Essentially I'm sending data to a Java Socket Server from an iPhone app however something rather strange happens, it doesn't receive the data until the iPhone application is closed! I'm sure there is something I'm missing but I just can't seem to find it, it's all quite odd.
Here is how my connection is created:
-(CFSocketRef)initSocket {
CFSocketContext context = {
.version = 0,
.info = self,
.retain = NULL,
.release = NULL,
.copyDescription = NULL
};
sockety = CFSocketCreate(
kCFAllocatorDefault,
PF_INET,
SOCK_STREAM,
IPPROTO_TCP,
kCFSocketDataCallBack^kCFSocketConnectCallBack,
socketCallBack,
&context
);
uint16_t port = 4444;
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(addr4));
addr4.sin_family = AF_INET;
addr4.sin_len = sizeof(addr4);
addr4.sin_port = htons(port);
const char *ipaddress = "192.168.1.5";
inet_aton(ipaddress, &addr4.sin_addr);
NSData *address = [NSData dataWithBytes:&addr4 length:sizeof(addr4)];
CFSocketError error = CFSocketConnectToAddress(sockety, (CFDataRef)address, 1);
if(error != kCFSocketSuccess )
{
Faliure = YES;
}
else{
ViewNo = 2;
}
CFRunLoopSourceRef source;
source = CFSocketCreateRunLoopSource(NULL, sockety, 1);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
CFRelease(source);
return sockety;
}
Heres how the message is sent:
const char *sendStrUTF = [sentmessage UTF8String];
NSData *dataOut = [NSData dataWithBytes: sendStrUTF length: strlen(sendStrUTF)];
CFSocketSendData(sockety, NULL, (CFDataRef) dataOut, 0);
Any help would be greatly appreciated!
Thanks in advance,
Ozzie
Is your call to CFSocketSendData being done on a (blocked) GUI thread?
I would experiment with wrapping those 3 lines in a performSelectorInBackground / or after delay combinations.
NSData *dat=[stringToSend dataUsingEncoding:NSASCIIStringEncoding];
CFSocketError w =CFSocketSendData(_socket, NULL,(CFDataRef)dat, 0);
if (w==kCFSocketSuccess) {
NSLog(#"success");
}
Related
I have legacy code using CFReadStreamRead on the iOS, but if there is no/loss of a connection CFReadStreamRead will block forever. How do I setup CFReadStreamRead to timeout?
Thanks in advance
#Michael Wildermuth Yes, there was an error on opening the stream and got it fixed. Someone who face the same issue, the below code would help.
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
CFStreamClientContext dataStreamContext = {0, (__bridge void *)(self), NULL, NULL, NULL};
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), (__bridge CFURLRef)url, kCFHTTPVersion1_1);
NSString *header;
NSDictionary *requestHeaders = [NSDictionary dictionaryWithObject:#"application/html;charset=UTF-8" forKey:#"Content-Type"];
for (header in requestHeaders) {
CFHTTPMessageSetHeaderFieldValue(message, (__bridge CFStringRef)header, (__bridge CFStringRef)[requestHeaders objectForKey:header]);
}
CFHTTPMessageSetBody(message, (CFDataRef)(CFSTR("")));
CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, message);
CFOptionFlags events = kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
if(CFReadStreamSetClient(readStream, events, EvenCallBack, &dataStreamContext)){
CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
}
CFReadStreamOpen(readStream);
And for the callback function,
void EvenCallBack(CFReadStreamRef readStream, CFStreamEventType type, void *clientCallBackInfo){
if(CFReadStreamHasBytesAvailable(readStream))
{
uint8_t buf[1024];
unsigned int len = 1024;
CFIndex numBytesRead = CFReadStreamRead(readStream, buf, len);
NSMutableData* data = [[NSMutableData alloc] init];
[data appendBytes:&buf length:numBytesRead];
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Network read (%d): %#", len, str);
}else {
return;
}
CFHTTPMessageRef message = (CFHTTPMessageRef)CFReadStreamCopyProperty((CFReadStreamRef)readStream, kCFStreamPropertyHTTPResponseHeader);
if (!message) {
NSLog(#"No message");
}
}
Thanks!
I ended up using a home grown timeout. The code was something like this:
uint64_t start = get_current_time();
while(TRUE) {
if(CFReadStreamHasBytesAvailable(stream) == TRUE) {
while ((bytes_read = CFReadStreamRead(stream, buffer, read_size)) > 0) {
// do work!
}
start = get_current_time();
}
uint64_t elapsed = get_current_time() - start;
if(elapsed > timeout) {
break;
}
sleep(10);
}
while ((bytes_read = CFReadStreamRead(stream, buffer, read_size)) > 0) {
// do work!
}
I don't think this code achieves anything special. CFReadStreamRead is internally implemented in a similar manner. Quoting Apple's documentation on this: "This function blocks until at least one byte is available; it does not block until buffer is filled."
I set a custom timeout method:
var hasRecievedUpdate = false
var httpStream: CFReadStream?
var handler: ((Data?, URLResponse?, Error?) -> Void)?
func send() {
let stream = httpStream as Stream
stream.delegate = self
stream.schedule(in: RunLoop.current, forMode: RunLoop.Mode.default)
stream.open()
hasRecievedUpdate = false
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + self.timeout) {
if !self.hasRecievedUpdate
{
stream.close()
self.handler?(nil, nil, nil)
}
}
}
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
self.hasRecievedUpdate = true
...
}
I have just started learning to design iphone apps and I am trying to set up a client server environment. As a starter I would like to first make sure that the service I publish is visible to the client. I have written server and client codes wit help from Apple's Docs. However I find that though my service is getting published (netServiceWillPublish(NSNetService *)sender is called), my client is not identifying this service. At the client's side the delegate function netServiceBrowserWillSearch:(NSNetServiceBrowser *)browser is called making me believe that the client is searching for the service. However the didFindService delegate function is never called. i am stumped as to why this is not working. I have followed the sample codes for the client side from various places and my code matches theirs. Some help on this would be greatly appreciated
Also I have the following questions
Can the service name (that comes along with the transport level protocol) be any string? Or does it have to be specified in http://www.dns-sd.org/ServiceTypes.html. Also what purpose does this solve apart from service discovery.
When I print out the details of the NSNetService object at the server's side (After setting up the socket and starting the service) the hostname is printed as (null) and there are no addresses being displayed. technically when a service is opened shouldn't these be set to values? If yes could someone please tell me where I am going wrong in my code?
I have attached the client and server code blocks of my project where the publishing and browsing of servicing is done. Help is extremely appreciated as I am stuck in my work with this issue.
This is the code snippet at the client side that browses for the services
NSNetServiceBrowser *serviceBrowser;
serviceBrowser = [[NSNetServiceBrowser alloc] init];
[serviceBrowser setDelegate:self];
[serviceBrowser searchForServicesOfType:#"_http._tcp." inDomain:#"local."];
This is the code snippet at the server side that publishes the service
BOOL success;
int fd;
int err;
int junk;
struct sockaddr_in addr;
NSInteger port;
port = 0;
fd = socket(AF_INET, SOCK_STREAM, 0);
success = (fd != -1);
if(success) {
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;
err = bind(fd, (const struct sockaddr*) &addr, sizeof(addr));
success = (err == 0);
}
if (success) {
err = listen(fd, 5);
success = (err == 0);
}
if (success) {
socklen_t addrLen;
addrLen = sizeof(addr);
err = getsockname(fd, (struct sockaddr *) &addr, &addrLen);
success = (err == 0);
if (success) {
assert( addrLen = sizeof(addr));
port = ntohs(addr.sin_port);
}
}
if (success) {
CFSocketContext context = { 0, (__bridge void *) self, NULL, NULL, NULL };
assert(self->_listeningSocket == NULL);
self->_listeningSocket = CFSocketCreateWithNative(NULL, fd, kCFSocketAcceptCallBack, AcceptCallBack, &context);
success = (self->_listeningSocket != NULL);
if (success) {
CFRunLoopSourceRef rls;
fd = -1; //listeningSocket is now responsible for closing the socket
rls = CFSocketCreateRunLoopSource(NULL, self.listeningSocket, 0);
assert(rls != NULL);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
}
}
if (success) {
self.netService = [[NSNetService alloc] initWithDomain:#"local." type:#"_http._tcp." name:#"test" port:port];
success = (self.netService != nil);
}
if (success) {
self.netService.delegate = self;
[self.netService publishWithOptions:NSNetServiceNoAutoRename];
}
if (success) {
assert(port != 0);
[self serverDidStartOnPort:port];
}
else {
[self stopServer:#"Start Failed"];
if (fd != -1) {
junk = close(fd);
assert(junk == 0);
}
}
This is the code snippet that tells that the service is published and prints out the details of my NSSocket object
- (void)netServiceWillPublish:(NSNetService *)sender {
NSLog(#"This function is getting called");
NSLog(#"sender.name %#",sender.name);
NSLog(#"sender.addresses %#",sender.addresses);
NSLog(#"sender.domain %#",sender.domain);
NSLog(#"sender.hostname %#",sender.hostName);
NSLog(#"sender.type %#",sender.type);
NSLog(#"sender.port %d",sender.port);
}
Thanks
Vivek
I need to convert a WAVE file into an AAC encoded M4A file on iOS. I'm aware that AAC encoding is not supported on older devices or in the simulator. I'm testing that before I run the code. But I still can't get it to work.
I looked into Apple's very own iPhoneExtAudioFileConvertTest example and I thought I followed it exactly, but still no luck!
Currently, I get a -50 (= error in user parameter list) while trying to set the client format on the destination file. On the source file, it works.
Below is my code. Any help is very much appreciated, thanks!
UInt32 size;
// Open a source audio file.
ExtAudioFileRef sourceAudioFile;
ExtAudioFileOpenURL( (CFURLRef)sourceURL, &sourceAudioFile );
// Get the source data format
AudioStreamBasicDescription sourceFormat;
size = sizeof( sourceFormat );
result = ExtAudioFileGetProperty( sourceAudioFile, kExtAudioFileProperty_FileDataFormat, &size, &sourceFormat );
// Define the output format (AAC).
AudioStreamBasicDescription outputFormat;
outputFormat.mFormatID = kAudioFormatMPEG4AAC;
outputFormat.mSampleRate = 44100;
outputFormat.mChannelsPerFrame = 2;
// Use AudioFormat API to fill out the rest of the description.
size = sizeof( outputFormat );
AudioFormatGetProperty( kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputFormat);
// Make a destination audio file with this output format.
ExtAudioFileRef destAudioFile;
ExtAudioFileCreateWithURL( (CFURLRef)destURL, kAudioFileM4AType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &destAudioFile );
// Create canonical PCM client format.
AudioStreamBasicDescription clientFormat;
clientFormat.mSampleRate = sourceFormat.mSampleRate;
clientFormat.mFormatID = kAudioFormatLinearPCM;
clientFormat.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
clientFormat.mChannelsPerFrame = 2;
clientFormat.mBitsPerChannel = 16;
clientFormat.mBytesPerFrame = 4;
clientFormat.mBytesPerPacket = 4;
clientFormat.mFramesPerPacket = 1;
// Set the client format in source and destination file.
size = sizeof( clientFormat );
ExtAudioFileSetProperty( sourceAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat );
size = sizeof( clientFormat );
ExtAudioFileSetProperty( destAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat );
// Make a buffer
int bufferSizeInFrames = 8000;
int bufferSize = ( bufferSizeInFrames * sourceFormat.mBytesPerFrame );
UInt8 * buffer = (UInt8 *)malloc( bufferSize );
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = clientFormat.mChannelsPerFrame;
bufferList.mBuffers[0].mData = buffer;
bufferList.mBuffers[0].mDataByteSize = ( bufferSize );
while( TRUE )
{
// Try to fill the buffer to capacity.
UInt32 framesRead = bufferSizeInFrames;
ExtAudioFileRead( sourceAudioFile, &framesRead, &bufferList );
// 0 frames read means EOF.
if( framesRead == 0 )
break;
// Write.
ExtAudioFileWrite( destAudioFile, framesRead, &bufferList );
}
free( buffer );
// Close the files.
ExtAudioFileDispose( sourceAudioFile );
ExtAudioFileDispose( destAudioFile );
Answered my own question: I had to pass this problem to my colleague and he got it to work! I never had the chance to analyze my original problem but I thought, I'd post it here for the sake of completeness. The following method is called from within an NSThread. Parameters are set via the 'threadDictionary' and he created a custom delegate to transmit progress feedback (sorry, SO doesn't understand the formatting properly, the following is supposed to be one block of method implementation):
- (void)encodeToAAC
{
RXAudioEncoderStatusType encoderStatus;
OSStatus result = noErr;
BOOL success = NO;
BOOL cancelled = NO;
UInt32 size;
ExtAudioFileRef sourceAudioFile,destAudioFile;
AudioStreamBasicDescription sourceFormat,outputFormat, clientFormat;
SInt64 totalFrames;
unsigned long long encodedBytes, totalBytes;
int bufferSizeInFrames, bufferSize;
UInt8 * buffer;
AudioBufferList bufferList;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSFileManager * fileManager = [[[NSFileManager alloc] init] autorelease];
NSMutableDictionary * threadDict = [[NSThread currentThread] threadDictionary];
NSObject<RXAudioEncodingDelegate> * delegate = (NSObject<RXAudioEncodingDelegate> *)[threadDict objectForKey:#"Delegate"];
NSString *sourcePath = (NSString *)[threadDict objectForKey:#"SourcePath"];
NSString *destPath = (NSString *)[threadDict objectForKey:#"DestinationPath"];
NSURL * sourceURL = [NSURL fileURLWithPath:sourcePath];
NSURL * destURL = [NSURL fileURLWithPath:destPath];
// Open a source audio file.
result = ExtAudioFileOpenURL( (CFURLRef)sourceURL, &sourceAudioFile );
if( result != noErr )
{
DLog( #"Error in ExtAudioFileOpenURL: %ld", result );
goto bailout;
}
// Get the source data format
size = sizeof( sourceFormat );
result = ExtAudioFileGetProperty( sourceAudioFile, kExtAudioFileProperty_FileDataFormat, &size, &sourceFormat );
if( result != noErr )
{
DLog( #"Error in ExtAudioFileGetProperty: %ld", result );
goto bailout;
}
// Define the output format (AAC).
memset(&outputFormat, 0, sizeof(outputFormat));
outputFormat.mFormatID = kAudioFormatMPEG4AAC;
outputFormat.mSampleRate = 44100;
outputFormat.mFormatFlags = kMPEG4Object_AAC_Main;
outputFormat.mChannelsPerFrame = 2;
outputFormat.mBitsPerChannel = 0;
outputFormat.mBytesPerFrame = 0;
outputFormat.mBytesPerPacket = 0;
outputFormat.mFramesPerPacket = 1024;
// Use AudioFormat API to fill out the rest of the description.
//size = sizeof( outputFormat );
//AudioFormatGetProperty( kAudioFormatProperty_FormatInfo, 0, NULL, &size, &outputFormat);
// Make a destination audio file with this output format.
result = ExtAudioFileCreateWithURL( (CFURLRef)destURL, kAudioFileM4AType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &destAudioFile );
if( result != noErr )
{
DLog( #"Error creating destination file: %ld", result );
goto bailout;
}
// Create the canonical PCM client format.
memset(&clientFormat, 0, sizeof(clientFormat));
clientFormat.mSampleRate = sourceFormat.mSampleRate;
clientFormat.mFormatID = kAudioFormatLinearPCM;
clientFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; //kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
clientFormat.mChannelsPerFrame = 2;
clientFormat.mBitsPerChannel = 16;
clientFormat.mBytesPerFrame = 4;
clientFormat.mBytesPerPacket = 4;
clientFormat.mFramesPerPacket = 1;
// Set the client format in source and destination file.
size = sizeof( clientFormat );
result = ExtAudioFileSetProperty( sourceAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat );
if( result != noErr )
{
DLog( #"Error while setting client format in source file: %ld", result );
goto bailout;
}
size = sizeof( clientFormat );
result = ExtAudioFileSetProperty( destAudioFile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat );
if( result != noErr )
{
DLog( #"Error while setting client format in destination file: %ld", result );
goto bailout;
}
// Make a buffer
bufferSizeInFrames = 8000;
bufferSize = ( bufferSizeInFrames * sourceFormat.mBytesPerFrame );
buffer = (UInt8 *)malloc( bufferSize );
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = clientFormat.mChannelsPerFrame;
bufferList.mBuffers[0].mData = buffer;
bufferList.mBuffers[0].mDataByteSize = ( bufferSize );
// Obtain total number of audio frames to encode
size = sizeof( totalFrames );
result = ExtAudioFileGetProperty( sourceAudioFile, kExtAudioFileProperty_FileLengthFrames, &size, &totalFrames );
if( result != noErr )
{
DLog( #"Error in ExtAudioFileGetProperty, could not get kExtAudioFileProperty_FileLengthFrames from sourceFile: %ld", result );
goto bailout;
}
encodedBytes = 0;
totalBytes = totalFrames * sourceFormat.mBytesPerFrame;
[threadDict setValue:[NSValue value:&totalBytes withObjCType:#encode(unsigned long long)] forKey:#"TotalBytes"];
if (delegate != nil)
[self performSelectorOnMainThread:#selector(didStartEncoding) withObject:nil waitUntilDone:NO];
while( TRUE )
{
// Try to fill the buffer to capacity.
UInt32 framesRead = bufferSizeInFrames;
result = ExtAudioFileRead( sourceAudioFile, &framesRead, &bufferList );
if( result != noErr )
{
DLog( #"Error in ExtAudioFileRead: %ld", result );
success = NO;
break;
}
// 0 frames read means EOF.
if( framesRead == 0 ) {
success = YES;
break;
}
// Write.
result = ExtAudioFileWrite( destAudioFile, framesRead, &bufferList );
if( result != noErr )
{
DLog( #"Error in ExtAudioFileWrite: %ld", result );
success = NO;
break;
}
encodedBytes += framesRead * sourceFormat.mBytesPerFrame;
if (delegate != nil)
[self performSelectorOnMainThread:#selector(didEncodeBytes:) withObject:[NSValue value:&encodedBytes withObjCType:#encode(unsigned long long)] waitUntilDone:NO];
if ([[NSThread currentThread] isCancelled]) {
cancelled = YES;
DLog( #"Encoding was cancelled." );
success = NO;
break;
}
}
free( buffer );
// Close the files.
ExtAudioFileDispose( sourceAudioFile );
ExtAudioFileDispose( destAudioFile );
bailout:
encoderStatus.result = result;
[threadDict setValue:[NSValue value:&encoderStatus withObjCType:#encode(RXAudioEncoderStatusType)] forKey:#"EncodingError"];
// Report to the delegate if one exists
if (delegate != nil)
if (success)
[self performSelectorOnMainThread:#selector(didEncodeFile) withObject:nil waitUntilDone:YES];
else if (cancelled)
[self performSelectorOnMainThread:#selector(encodingCancelled) withObject:nil waitUntilDone:YES];
else
[self performSelectorOnMainThread:#selector(failedToEncodeFile) withObject:nil waitUntilDone:YES];
// Clear the partially encoded file if encoding failed or is cancelled midway
if ((cancelled || !success) && [fileManager fileExistsAtPath:destPath])
[fileManager removeItemAtURL:destURL error:NULL];
[threadDict setValue:[NSNumber numberWithBool:NO] forKey:#"isEncoding"];
[pool release];
}
Are you sure the sample rates match? Can you print the values for clientFormat and outputFormat at the point you’re getting the error? Otherwise I think you might need an AudioConverter.
I tried out the code in Sebastian's answer and while it worked for uncompressed files (aif, wav, caf), it didn't for a lossy compressed file (mp3). I also had an error code of -50, but in ExtAudioFileRead rather than ExtAudioFileSetProperty. From this question I learned that this error signifies a problem with the function parameters. Turns out the buffer for reading the audio file had a size of 0 bytes, a result of this line:
int bufferSize = ( bufferSizeInFrames * sourceFormat.mBytesPerFrame );
Switching it to use the the bytes per frame from clientFormat instead (sourceFormat's value was 0) worked for me:
int bufferSize = ( bufferSizeInFrames * clientFormat.mBytesPerFrame );
This line was also in the question code, but I don't think that was the problem (but I had too much text for a comment).
I have a problem with my socket program.
I create the client program (my code is below)
I have a problem when i close the socket with the disconnect method.
CFSocketRef s;
-(void)CreaConnessione
{
CFSocketError errore;
struct sockaddr_in sin;
CFDataRef address;
CFRunLoopSourceRef source;
CFSocketContext context = { 0, self, NULL, NULL, NULL };
s = CFSocketCreate(
NULL,
PF_INET,
SOCK_STREAM,
IPPROTO_TCP,
kCFSocketDataCallBack,
AcceptDataCallback,
&context);
memset(&sin, 0, sizeof(sin));
int port = [fieldPorta.text intValue];
NSString *tempIp = fieldIndirizzo.text;
const char *ip = [tempIp UTF8String];
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = (long)inet_addr(ip);
address = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin));
errore = CFSocketConnectToAddress(s, address, 0);
if(errore == 0){
buttonInvioMess.enabled = TRUE;
fieldMessaggioInvio.enabled = TRUE;
labelTemp.text = [NSString stringWithFormat:#"Connesso al Server"];
CFRelease(address);
source = CFSocketCreateRunLoopSource(NULL, s, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
source,
kCFRunLoopDefaultMode);
CFRelease(source);
CFRunLoopRun();
}
else{
labelTemp.text = [NSString stringWithFormat:#"Errore di connessione. Verificare Ip e Porta"];
switchConnection.on = FALSE;
}
}
//the socket doesn't disconnect
-(void)Disconnetti{
CFSocketInvalidate(s);
CFRelease(s);
}
-(IBAction)Connetti
{
if(switchConnection.on)
[self CreaConnessione];
else
[self Disconnetti];
}
If you're trying to reuse the socket which you have invalidated. I guess you cant use the same socket object again.
because once i remove invalidating socket from my code. the code works pretty good on every single time i try to make connection after disconnecting..
How can i send image over socket in iPhone. I tried with string the code i used is as follows, now i need to send image over socket.
CFWriteStreamRef writeStream = NULL;
CFStringRef host = CFSTR("192.168.1.211");
UInt32 port = 8001;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, NULL, &writeStream);
CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
if(!CFWriteStreamOpen(writeStream)) {
NSLog(#"Error Opening Socket");
}
else{
UInt8 buf[] = "Abc";
int bytesWritten = CFWriteStreamWrite(writeStream, buf, strlen((char*)buf));
NSLog(#"Written: %d", bytesWritten);
if (bytesWritten < 0) {
CFStreamError error = CFWriteStreamGetError(writeStream);
}
}
Regards,
The image has to be converted to base64 string and transferred through socket.
Here is the code snippet for base-64 conversion in Objective c
- (NSString *)encodeToBase64String:(UIImage *)image {
return [UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
Swift
let strBase64:String = imageData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
Here is the reference