I'm trying to use a socket framework to connect to a socket I have. I am able to connect just fine with raw socket code like:
uint portNo = 9900;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"123.456.789.159", portNo, &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];
but when I try with any framework I get an error and I'm completely stumped as to why. I've tried SocketRocket and Jetfire. Here's the code for connecting in SocketRocket that I've tried:
_webSocket.delegate = nil;
[_webSocket close];
_webSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:#"wss://123.456.789.159"]];
_webSocket.delegate = self;
NSLog(#"Opening Connection...");
[_webSocket open];
I've also tried with the port number added.
_webSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:#"wss://123.456.789.159:9900"]];
Also tried with http, https, ws. Still nothing.
Anybody have an idea as to why?
WebSocket is a protocol for bringing raw socket like functionality on top of HTTP. The socket that your server is exposing likely does not support the WebSocket protocol.
If you want a higher-level API for raw socket programming on iOS, CocoaAsyncSocket might be a good option for you.
Related
I am developing a Mac application to communicate with printers using socket. When communicate with one printer with IPv4 ip, i got response. But when i tried using IPv6 IP with the second printer i got error
SocketStream write error [0x0]: 1 9
Error reading stream! ,Error 9: The operation couldn’t be completed.
Bad file descriptor
I use CFStreamCreatePairWithSocketToHost function for the communication. Do i need to do anything when communicate with IPv6 ip.
NSURL *myUrl = [NSURL URLWithString:#"fe80::aee2:d3ff:feff:46c7"];
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)myUrl.path, 8080, &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];
I was working in Socket Communication in iOS. below is the code i have done.
- (void)TcpClientInitialise
{
NSLog(#"Tcp Client Initialise");
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)_IPAddress.text,(int)_port.text.integerValue, &readStream, &writeStream);
[consoleLog appendString:[NSString stringWithFormat:#"IPAddress - %# and port %d \n", _IPAddress.text,(int)_port.text.integerValue]];
_console.text = consoleLog;
[InputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey: (__bridge NSString *)kCFStreamPropertySSLSettings];
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];
}
but i not able initiate the connection. the problem is the Host is Enable with the SSL certificate. My Server team has said i have connect to the host with the certificate. and they have given the certificate. which is "digicert.crt"
Please help me how to connect to the host with using the certificate.
I've written a server with Python (Twisted) and now want to connect it with iOS, but having some trouble.
This is how I connect to the server:
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 3000, &readStream, &writeStream);
inputStream = (NSInputStream *)readStream;
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];
The problem comes with the RunLoop. Imagine that I wan't to send to the server one message. Then I would do:
NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
BUT what if I wan't to send TWO messages, one after the other? Then I could run the code with message1 and message2... but then what the client really sends is a concatenation of message1+message2, not two different messages. I guess this is because I write the messages to the outputStream in the same "loop", so when the stream finally decides to send the data, it sends both... I can't figure out any solution. The same happens if SERVER sends more than one message to CLIENT "very fast". What should I do?
Define the "protocol" - basically a "grammar" which defines the "language" which will be understood by the participants.
The simplest approach would be to define tokens and separators and a corresponding parser.
For example you might define a message consisting of a single char, and multiple messages will be separated by one or more spaces. Then you can send this over the wire:
A B C D E
Using this very helpful tutorial, I've been able to put together a test (video) of socket communication between the iOS Simulator and Maya. This is working very well with the simulator and localhost. However, when I test it on my device over the same wireless network, the iOS application just hangs with no connection with Maya (upon connection, there's a little "heads-up" message that displays).
I'm new to iOS programming and socket programming in particular, but I'm wondering if I'm missing anything. Here's the method I'm calling with the "connect" button press:
- (void) initNetworkCommunication {
//assign text inputs to variables
self.ipAddress = self.inputIPAddress.text;
self.portNumber = [self.inputPortNumber.text intValue];
//create streams and use variables to populate connection method
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(self.ipAddress), self.portNumber, &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];
//send initial message to Maya
NSString *initResponse = [NSString stringWithFormat:#"cmds.headsUpMessage('connected to iPhone')"];
NSData *initData = [[NSData alloc] initWithData:[initResponse dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[initData bytes] maxLength:[initData length]];
//need some error checking or timeout mechanism
}
Like I said, works like a charm with localhost, but fails over the wireless network.
Okay, found my own answer by digging through someone else's python script for creating a commandPort in Maya. It actually isn't due to the iOS code at all. It turns out that in Maya I need to create a commandPort using not only a port number but also the ip address. My mistake was that I assumed the commandPort knew the local ip address or didn't care. Apparently it cares.
Before (simplified code):
cmds.commandPort (n=':6328', stp='python')
After:
cmds.commandPort (n='192.168.2.7:6328', stp='python')
I have been working on a NSStreamDelegate, I have implemented call back, I have initialized the input and output stream ilke this...
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStringRef host = CFSTR("74.125.224.72");
UInt32 port = 2270;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &inputStream, &writeStream);
if (writeStream && inputStream) {
inputStream = (__bridge NSInputStream *)readStream;
[inputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
outputStream = (__bridge NSOutputStream *)writeStream;
[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream open];
}
Even after opened both the stream callback(stream:(NSStream *)theStream handleEvent:) is not called with NSStreamEventOpenCompleted for both streams. Can anyone help me what am I doing wrong here. Or What is the possibilities NSStreamEventOpenCompleted won't be called, I have seen in documentation, if opening failed it will not call this, if so why opening of streams is failing. Any idea?
thanks for your help.
I use with very similar code and it works fine for me.
Try the code below.
NSString* host = #"192.168.2.105";
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
UInt32 port = 8008;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)(host), port, &readStream, &writeStream);
if (writeStream && readStream) {
self.InputStream = (__bridge NSInputStream *)readStream;
[self.InputStream setDelegate:self];
[self.InputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.InputStream open];
self.OutputStream = (__bridge NSOutputStream *)writeStream;
[self.OutputStream setDelegate:self];
[self.OutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[self.OutputStream open];
}
If it doesn't work for you, I can to send you a small app that implement TCP Client and server for a example.
If it is running in a new NSThread, make sure the run loop of the thread is started after the stream setup, like CFRunLoopRun();