Connect to UDP server - ios

I'm try to create an application for iOS, where I can connect to a UDP Server and receive data from it. My situation:
I have a UDP server on Windows machine (IP = 192.168.1.6).
I have iPad (IP = 192.168.1.5);
UDP server sends to virtual address (IP = 239.254.1.2) and port (7125) messages, something like "HELLO!!!!! I'm here!!!!"
I need add some logic for the iOS app, where I can connect to virtual IP address (IP = 239.254.1.2) and port (7125) and receive messages "HELLO!!!!! I'm here!!!!" from UDP server.
Does anyone have any suggestions?
UPDATE1:
For UDP connection I'm use GCDAsyncUdpSocket
Here my code:
#interface ViewController () {
GCDAsyncUdpSocket *udpSocket;
}
- (void)viewDidLoad {
[super viewDidLoad];
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
}
- (IBAction)startStop:(id)sender {
if (isRunning) {
// STOP udp echo server
[udpSocket close];
[self logInfo:#"Stopped Udp Echo server"];
isRunning = false;
[portField setEnabled:YES];
[startStopButton setTitle:#"Start" forState:UIControlStateNormal];
} else {
// START udp echo server
int port = [portField.text intValue];
if (port < 0 || port > 65535) {
portField.text = #"";
port = 0;
}
NSError *error = nil;
if (![udpSocket bindToPort:7125 error:&error]) {
[self logError:FORMAT(#"Error starting server (bind): %#", error)];
return;
}
if (![udpSocket joinMulticastGroup:#"239.254.1.2" error:&error]) {
[self logError:FORMAT(#"Error join Multicast Group: %#", error)];
return;
}
if (![udpSocket beginReceiving:&error])
{
[udpSocket close];
[self logError:FORMAT(#"Error starting server (recv): %#", error)];
return;
}
[self logInfo:FORMAT(#"Udp Echo server started on port %hu", [udpSocket localPort])];
isRunning = YES;
[portField setEnabled:NO];
[startStopButton setTitle:#"Stop" forState:UIControlStateNormal];
}
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
if (!isRunning) return;
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (msg)
{
/* If you want to get a display friendly version of the IPv4 or IPv6 address, you could do this:
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
*/
[self logMessage:msg];
}
else
{
[self logError:#"Error converting received data into UTF-8 String"];
}
[udpSocket sendData:data toAddress:address withTimeout:-1 tag:0];
}
When I press "Start" button in the log I see message "Udp Echo server started on port 7125", but delegate method
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
never fired and application dont receive any messages from virtual IP address.
Can you help me with this issue?
Thank you.

239.254.1.2 is a multicast address that the UDP server is sending packets to. Anyone listening on that address will receive the packets. So:
create a UDP socket
bind your socket to port 7125
join the multicast group 239.254.1.2
your app will start receiving the udp packets
Probably should just mention that UDP is connectionless protocol, i.e. you cannot connect to a UDP server.

RichardBrock was right and sample code from UPDATE1 works perfectly. Problem was with my home Network, and when I tryed this code in the work Network everything works fine!!!
Thanks you

Related

GCDAsyncSocket readData not called

I'm trying to send a message to a server and receive a response using my iPhone. I can connect to the server using:
telnet 123.123.123.1 6000
Trying 123.123.123.1...
Connected to 123.123.123.1.
Escape character is '^]'.
?VERSION
OK
VERSION=PROTOCOL: 1.1.0
?VERSION is my question
OK states it received and understood the question
VERSION= is the response from the server
so I'm trying to do the same thing but with xcode
So I have this in my viewDidLoad
dispatch_queue_t mainQueue = dispatch_get_main_queue();
asyncSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:mainQueue];
asyncSocket.delegate = self;
NSString *host = #"123.123.123.1";
uint16_t port = 6000;
NSLog(#"Connecting to \"%#\" on port %hu...", host, port);
NSError *error = nil;
if (![asyncSocket connectToHost:host onPort:port withTimeout:5.0 error:&error])
{
NSLog(#"Error connecting: %#", error);
}
else
{
NSLog(#"Connecting...");
}
And I have the following code showing it connected
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:
(UInt16)port
{
NSLog(#"socket:%p didConnectToHost:%# port:%hu", sock, host, port);
// We're just going to send a test string to the server.
NSString *myStr = #"?VERSION";
NSData *myData2 = [myStr dataUsingEncoding:NSUTF8StringEncoding];
[asyncSocket writeData:myData2 withTimeout:-1 tag:0];
}
And the following to show it wrote
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
NSLog(#"WRITING");
[asyncSocket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:0];
}
Sadly this never gets called
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSString *tempString = [[NSString alloc]initWithData:data
encoding: NSUTF8StringEncoding];
}
I'm lost and really need some assistance
It is because you say write AND read at the same time. First call [asyncSocket writeData:myData2 withTimeout:-1 tag:0]; and in didWriteDataWithTag call [asyncSocket readDataToData:[GCDAsyncSocket LFData] withTimeout:-1 tag:0];. You are on one thread - dispatch_get_main_queue() - it can't do two things at one time.

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

why GCDAsyncUdpSocket cannot send/receive packets after a while in broadcast mode?

I am using GCDAsyncUdpSocket to write a UDP socket in my app. The scenario is like this: when users click the button, it will send a broadcast packet in LAN then listen to the response, there is a server in LAN which will respond with one UDP packet. When the app receives the response, it will do something.
I set GCDAsyncUdpSocket as followings:
- (void)setupSocket
{
_udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![_udpSocket bindToPort:18686 error:&error]) {
NSLog(#"Error binding: %#",error);
return;
}
if (![_udpSocket beginReceiving:&error]) {
NSLog(#"Error receiving: %#",error);
return;
}
if (![_udpSocket enableBroadcast:YES error:&error]) {
NSLog(#"Error enableBroadcast: %#",error);
return;
}
}
then i send Packet in button action as following:
NSString *host = #"255.255.255.255";
int port = 8585;
NSString *msg = #"Hello from iOS";
NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
[_udpSocket sendData:data toHost:host port:port withTimeout:-1 tag:0];
in
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
method i listen the port to do somethings. It works perfectly at beginning, but if you try to click the button later (about 1 hour), then it cannot send UDP packet any more.
My server in LAN will print the data received. I thought there was something wrong with send method. so i use BSD socket methods to send The data. and use GCDAsyncUdpSocket to receive the response. but the same thing happened after a while. this time i can send but cannot receive.
Am i missing something about GCDAsyncUdpSocket? why it cannot send/receive after a while? Any help would be much appreciated.
It may be some timeout setting. Implement the GCDAsyncUdpSocketDelegate protocol to fetch detailed information about what is going on.
The hard solution is to establish a new connection.

Node JS udp broadcast not read -- node js and iOS

here is my code (javascript for node):
var dgram = require('dgram');
var message = new Buffer("why hello beautiful");
var client = dgram.createSocket("udp4");
client.bind(41234);
client.setBroadcast(true);
client.send(message, 0, message.length, 41234, "134.71.147.255");
console.log('msg sent');
client.close();
here is the ifconfig for my computer running node (the only pertinent thing I think -- correct me if im wrong please):
inet addr:134.71.146.49 Bcast:134.71.147.255 Mask:255.255.254.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
The udp broacast is neither recieved on my iOS app nor visible through a packet inspector.
What is going wrong?! The iOS app uses the GCDAsyncUdpSocket framework:
- (void) initUDPlistener {
NSLog(#"initUDPlistener");
udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *error = nil;
if (![udpSocket bindToPort:UDP_PORT error:&error]) //does the port matter? i dont know
{
return;
}
if (![udpSocket beginReceiving:&error])
{
return;
}
[udpSocket enableBroadcast:YES error:nil];
[udpSocket sendData:[self pack:#"iOS to bcast"] toHost:UDP_BCAST_ADDR port:UDP_PORT withTimeout:-1 tag:0];
}
#pragma mark -
#pragma mark Delegate UDP methods
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
NSLog(#"niets.");
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (msg)
{
NSLog(#"iets gekregen");
}
else
{
NSLog(#"Error convertion");
}
NSLog(#"HMMMM");
}
-(void) udpSocket:(GCDAsyncUdpSocket *) sock didSendDataWithTag:(long)tag {//called. and packet inspector recieves the packet when it is sent OUT from the iOS app.
NSLog(#"written data tag: %ld", tag);
}
-(void) udpSocket:(GCDAsyncUdpSocket *)sock didConnectToAddress:(NSData *)address { //never called
NSLog(#"connected to some address");
}
What happens:
"didReceiveData" does not get called from the node broadcast. It gets called when it sends its own message out, however.
the iOS app, on the other hand, successfully broadcasts and i am able to intercept that packet on my packet inspector. The same packet inspector does not show packets that should be originating from Node, however.
what am I doing wrong in node? I think what I am doing in node is the problem.

sending UDP request to 255.255.255.255 and waiting for reply in iOS

Im would to send a UDP broadcast from an iPhone, and then listen for a UDP response with a timeout period from all devices with such port opened. Does my custom device from the same subnet would answer? ( if mine is 192.168.1.100 and IP of custom device is 192.168.1.201 )
What to use "SmallSockets" or "cocoaAsyncSocket" ?
What function to use to listen for response?
Thanx!
i decided to use cocoaAsyncSocket.
To broadcast you can use:
[udpSocket sendData:datatosend toHost:#"192.168.1.113" port:port withTimeout:-1 tag:0];
to receive:
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data fromAddress:(NSData *)address withFilterContext:(id)filterContext
{
NSString *msg = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSString *host = nil;
uint16_t port = 0;
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
if (msg)
{
NSLog(#"Message = %#, Adress = %# %i",msg,host,port);
}
else
{
NSLog(#"Error converting received data into UTF-8 String");
}
}

Resources