Objective-C Sockets Send and Receive on iOS - ios

I'm very new to Objective-C and would like to communicate between an iOS app which I'm working on and my Python 3 socket server (which works). The problem is I don't know how to use sockets in Objective-C and don't know where to start when installing libraries in Xcode 8. For now I just want to be able to send data to the server and receive a response back on the iOS device. I have seen sys.socket.h but again, I don't know how to use it, any help would be much appreciated.
Thanks!

Few years ago I used SocketRocket. I am posting some of the code of it from my old project. I don't know if that still works but you might get the idea of using it.
Connecting to server
NSMutableURLRequest *pushServerRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"ws://192.168.1.1"]];
[pushServerRequest setValue:#"WebSocket" forHTTPHeaderField:#"Upgrade"];
[pushServerRequest setValue:#"Upgrade" forHTTPHeaderField:#"Connection"];
[pushServerRequest setValue:"somekey" forHTTPHeaderField:#"Sec-WebSocket-Protocol"];
SRWebSocket *wsmain = [[SRWebSocket alloc] initWithURLRequest:pushServerRequest]; //Declare this as a global variable in a header file
wsmain.delegate=self;
[wsmain open];
Delegate Methods
-(void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
{
NSLog(#"Message %#",message);
}
- (void)webSocketDidOpen:(SRWebSocket *)webSocket
{ NSLog(#"Connected");
}
Sending Commands
[wsmain send:commands];
By sending commands, you will receive a response in didReceiveMessage method.

have you seen https://github.com/robbiehanson/CocoaAsyncSocket?
It's easy to use socket
NSString *host = #"10.70.0.22";
int port = 1212;
_socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
NSError *error = nil;
[_socket connectToHost:host onPort:port error:&error];
if (error) {
NSLog(#"%#",error);
}
delegate
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
NSLog(#"success");
}
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
if (err) {
NSLog(#"error %#",err);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self connectToServer];
});
}else{
NSLog(#"disconnect");
}
}

Another option is socket.io. It has server libraries and a iOS client library written in Swift. It's API is quite extensive.

Related

{"code":1,"message":"Session ID unknown"} while connecting users to socket.io for first attempt

I am developing chat application using socket.io in objective-c. I am facing issue of loosing offline messages.
The scenario is while I have couple of offline messages in queue, when client(iOS App) is connected. Initially it disconnects directly saying "Session ID Unknown".
Below is the code of connection using socket
NSURL* url = [[NSURL alloc] initWithString:#"MYURL"];
self.socket = [[SocketIOClient alloc] initWithSocketURL:url config:#{#"log": #NO, #"reconnectAttempts" : #50, #"reconnects" : #YES, #"forcePolling": #YES}];
if (![self.socket.engine connected])
{
[self.socket connectWithTimeoutAfter:20000 withHandler:^{
NSLog(#"Socket Conencted");
}];
}
[self.socket off:#"disconnect"];
[self.socket off:#"error"];
[self.socket off:#"add user"];
[self.socket off:#"private message"];
[self.socket off:#"connect"];
[self.socket off:#"startChat"];
[self.socket off:#"delivered"];
[self.socket off:#"user image"];
[self.socket off:#"received server"];
[self.socket on:#"connect" callback:^(NSArray * data, SocketAckEmitter * ack) {
}];
[self.socket on:#"user image" callback:^(NSArray * data, SocketAckEmitter * ack) {
}];
.....
Logs_Application.txt
Chat working properly but some times it loosing messages and delivery reports.
However, this kind of issue is not observed in all users, but couple of users are facing this kind of issue.
Looking forward to hear with some solution for the same.
Let me know if I can provide more information for better understanding the issue.

Twillio Client To Client Call ios Never Recieve call method is didReceiveIncomingConnection

I am working on iOS application where I am using Twilio SDK to manage client calling through device. To implement this i am using hello monkey demo application which i have successfully imported in Xcode.
After initial setup i am able to establish connection successfully but receiving delegate is no longer working. I have gone through complete twilio documentation but no success. Please suggest any alternative or solution ASAP.
Here is my code of Hello Monkey sample project
- (void)viewDidLoad
{
NSLog(#"CLINT ID----------------------- %#",name);
//check out https://github.com/twilio/mobile-quickstart to get a server up quickly
NSString *urlString = [NSString stringWithFormat:#"https://testdemo786.herokuapp.com/token?client=%#", name];
NSURL *url = [NSURL URLWithString:urlString];
NSError *error = nil;
NSString *token = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (token == nil) {
NSLog(#"Error retrieving token: %#", [error localizedDescription]);
} else {
_phone = [[TCDevice alloc] initWithCapabilityToken:token delegate:self];
}
}
- (IBAction)dialButtonPressed:(id)sender
{
NSString *to;
if ([name isEqualToString:#"jenny"]) {
to=#"client:tommy";
}
else
{
to=#"client:jenny";
}
to=#"4nmf5j";
NSLog(#"TO---------------------%#",to);
NSDictionary *params = #{#"To": to};
_connection = [_phone connect:params delegate:nil];
}
- (IBAction)hangupButtonPressed:(id)sender
{
[_connection disconnect];
}
- (void)device:(TCDevice *)device didReceiveIncomingConnection:(TCConnection *)connection
{
NSLog(#"Incoming connection from: %#", [connection parameters][#"From"]);
if (device.state == TCDeviceStateBusy) {
[connection reject];
} else {
[connection accept];
_connection = connection;
}
}
-(void)connection:(TCConnection*)connection didFailWithError: (NSError*)error{
NSLog(#"Connection failed with error : %#", error);
}
-(void)connectionDidStartConnecting:(TCConnection*)connection{
NSLog(#"connection started");
}
-(void)connectionDidDisconnect:(TCConnection*)connection{
NSLog(#"connection disconnected");
}
-(void)connectionDidConnect:(TCConnection*)connection{
NSLog(#"connected");
}
- (void)deviceDidStartListeningForIncomingConnections: (TCDevice*)device
{
NSLog(#"Device: %# deviceDidStartListeningForIncomingConnections", device);
}
- (void)device:(TCDevice *)device didStopListeningForIncomingConnections:(NSError *)error
{
NSLog(#"Device: %# didStopListeningForIncomingConnections: %#", device, error);
}
Twilio evangelist here.
Its a bit hard to tell from the code you included, which does look correct to me.
Here are a couple of things to check:
Did you add the TCDeviceDelegate as a protocol on your interface:
#interface FooViewController() <TCDeviceDelegate>
Are you sure you passing the correct client name to the connect method, and that the TwiML being returned from your TwiML Apps Voice Request URL is including that name properly?
You could check this by looking at the Twilio Monitor to see if Twilio logged any errors when retrieving or parsing your TwiML. You can also check your Twilio call logs to see what Twilio says the outcome of the inbound and outbound call legs were.
Hope that helps.
did you set the delegate to self?
_device = [[TCDevice alloc] initWithCapabilityToken:capabilityToken delegate:self];

Can't get an NSString from one file to another

I'm developing an application which is connecting to another device and in order to connect to it my app has to find the IP of it. I'm doing it through UDP socket. I'm sending a message to the server application in the other device and then the server app sends me another message but after I receive it I only use the IP address. Then I want to get it from this .m file to another .m file which is going to make the TCP connection between the two devices. Here's the code I use:
NSString *SearchCommand = #"AT+S";
static int receivedByteCount = 0;
BOOL connectedThroughUDP;
- (void) activate {
connectedThroughUDP = NO;
AsyncUdpSocket *udpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
[udpSocket bindToPort:1234 error:nil ];
[udpSocket enableBroadcast:YES error:nil];
NSData* data=[SearchCommand dataUsingEncoding:NSUTF8StringEncoding];
if ([udpSocket sendData:data toHost:#"255.255.255.255" port:30100 withTimeout:3 tag:0])
{
//2 second timeout. onUdpSocket methods will provide results
[udpSocket receiveWithTimeout:2 tag:0];
NSLog(#"Connected.");
}
}
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port{
NSString *receiveddata = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
addressOfServer = host;
NSLog(#"addressOfServer = %#", addressOfServer);
connectedThroughUDP = YES;
return YES;
}
- (NSString *) getHost {
return addressOfServer;
}
- (BOOL) isItConnected {
return connectedThroughUDP;
}
addressOfServer is global variable.
In the Log when I want NSLog(#"addressOfServer = %#", addressOfServer); I receive the IP address which I want but then when I want to access it from the getHost method I receive (null).
I know it will be something very simple but it caused me a real headache in the past 3 hours so I would be very thankful if you can help me!
Are you calling these 3 lines right after each other like so:
UDPConnection *udpConnection = [[UDPConnection alloc] init];
[udpConnection activate];
host = [udpConnection getHost];
If so your issue is that [udpConnection activate]; is going to take some time to connect and figure out the address. You are calling [udpConnection getHost]; too soon.
You will need to setup a delegate or completion block that will be triggered when didReceiveData is fired

ios Read data at fast rate in UDP

i am establishing a UDP connection using GCDAsyncSocket(ios device). Everything working fine and im able to send and receive messages, my problem is that i want to exchange data fast. I can send pretty fast data from my iphone to a pc but i cant get at that speed data from pc, more specific i want to be able to get data every 100ms.
I use this function when i connect successfully:
-(void)startRead {
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(startRead) userInfo:nil repeats:YES];
[asyncSocket readDataWithTimeout:-1 tag:0];
}
With this i can read data with 1sec interval but if i try to put 0.1 seconds my program freezes.(Same with values under 1second) Im sure that im doing something wrong here and there will be a way to achieve what i want so if anybody know plz help!!
thanx
I believe the above comment is correct, you've not set the Delegate correctly on init. The socket creation should be something like this
GCDAsyncUdpSocket* udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:0 error:&error])
{
[self logError:[NSString stringWithFormat:#"Error binding: %#", error]];
return;
}
if (![udpSocket beginReceiving:&error])
{
[self logError:[NSString stringWithFormat:#"Error receiving: %#", error]];
return;
}
NSString *_host = nil;
uint16_t _port = 0;
[GCDAsyncUdpSocket getHost:&_host port:&_port fromAddress:udpSocket.localAddress];
[self logInfo:[NSString stringWithFormat:#"Socket setup on host %#:%d", _host, _port]];
[self logInfo:#"Socket created successfully."];
Unless you're using a different version of GCDAsyncUdpSocket than I'm familiar with, the correct callback method is actually the below method. This is called automatically when the delegate is set and a packet is received on the correct port.
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext

iPad GCDAsyncSocket doesn't read

I really need some help with my project...
I need to exchange data with my server written in Java. I tried using GCDAsyncSocket, and I can send message to server, read it on server, but when server sends response to client, I can't (don't know how to) read it on client. Here is part of my code:
- (void) someMethod{
NSError *err = nil;
asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
if(![asyncSocket connectToHost:#"localhost" onPort:7777 error:&err]){
// If there was an error, it's likely something like "already connected" or "no delegate set"
NSLog(#"I goofed: %#", err);
}
NSString *requestStr = #"<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><root><service>1</service><type>1</type><userProperties><username>ivo</username></userProperties></root>";
NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:requestData withTimeout:-1.0 tag:0];
[asyncSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:1.0 tag:0];
[asyncSocket disconnectAfterWriting];
}
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
if (tag == 0)
NSLog(#"First request sent");
else if (tag == 2)
NSLog(#"Second request sent");
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",str);
}
Please help, if there is another way I am willing to try as I am getting desperate...
I see that you're sending XML, with no particular terminator at the end of your request data, yet you're expecting the server to send a response terminated by a \r\n?
What does the protocol specify?
Sending and receiving data over tcp is a common cause of confusion because tcp is stream based. It has no concept of individual reads/writes. It treats all data as conceptually a never ending stream. The protocol dictates message boundaries. For a better explanation, see the "Common Pitfalls" article from GCDAsyncSocket's wiki:
https://github.com/robbiehanson/CocoaAsyncSocket/wiki/CommonPitfalls
I think it will help explain a lot.

Resources