I've just begun developing with networking on the iPhone. I need to develop a simple app for talking to a Wifi router. The thing is, the wifi box communicates over UDP. I've dug around quite a bit, but all the sample code I've seen so far, have examples for TCP comms, except for one; the UDPEcho example.
So, my questions are: 1. How do I know if a device on a WiFi network can be connected on WiFi? 2. For communicating on UDP, can I simply create a socket, and send data using the CFSocketSendData method to some address?
It seemds like the UDPEcho example, first creates a host, then resolves it, then gets an address, and after binding to a socket sends some data. I want a simplistic raw implementation for simply sending a packet and receiving a packet in response.
Any links or references will be helpful. Even more helpful, will be some basic steps for a raw implementation. In simple terms, can I do the following: 1. Create a socket using CFSocketCreate, specifying a callback when data is available for reading. 2. Send data on the socket using CFSocketSend, specifying the address I would like to send.
EDIT: I created a class SocketTest and then called connect: followed by sendData. Here's the code:
#include "SocketTest.h"
@implementation SocketTest
- (BOOL)connectSocket{
CFSocketRef appSocket;
const CFSocketContext socketContext = { 0, self, NULL, NULL, NULL };
CFRunLoopSourceRef socketRunLoopSourceRef;
struct sockaddr_in deviceAddress;
/**
We have to bind a machine address to the socket which we will create. For this,
we need to store our address and port number into a structure of the type,
struct_sockaddr_in (since, we will be using IPv4).
*/
/**
Part 1: Create address structure.
*/
//Clear memory reserved for socket address.
memset(&deviceAddress, 0, sizeof(deviceAddress));
//Create our remote device address
deviceAddress.sin_addr.s_addr = inet_addr("192.168.0.1"); //Convert string to suitable usage format and store as address.
deviceAddress.sin_family = AF_INET;
deviceAddress.sin_port = (u_short)9009;
//Put the device address into a CFDataRef object.
CFDataRef address = CFDataCreate(NULL, (UInt8 *)&deviceAddress, sizeof(struct sockaddr_in));
//If there was a problem with previous call, return with error.
if (NULL == address) {
return 1;
}
/**
Part 2: Create socket with a signature and add it to run loop.
*/
//Create a socket signature that specifies the communication protocol and the connection address.
const CFSocketSignature signature = {
PF_INET, //Protocol family IPv4
SOCK_DGRAM, //Datagram socket
IPPROTO_UDP, //Protocol is UDP
address //CFDataRef object holding the contents of our remote address.
};
//Create socket with the signature just created
appSocket = CFSocketCreateConnectedToSocketSignature(
NULL, //Default memory allocator
&signature, //Signature we created above
kCFSocketDataCallBack, //Callback that will read data into a CFData object
dataReadyToRead, //The method that will be called as callback
&socketContext,
0.0
);
//Create socket
/*
appSocket = CFSocketCreate(
NULL, //Default memory allocator
PF_INET, //Protocol Family IPv4
SOCK_DGRAM, //Datagram socket (UDP)
IPPROTO_UDP, //Protocol is UDP
kCFSocketDataCallBack, //Flag to tell socket to call our callback when data is ready
dataReadyCallBack, //The call back function that will be called
&socketContext //The socket context
);
*/
//Create run loop source, with our socket as the source
socketRunLoopSourceRef = CFSocketCreateRunLoopSource(
NULL, //Default memory allocator
appSocket, //Socket created
0 //Highest priority source
);
//Add to surrent run loop
CFRunLoopAddSource(
CFRunLoopGetCurrent(), //Add to current run loop
socketRunLoopSourceRef, //Add this run loop source
kCFRunLoopDefaultMode //The default mode of the run loop
);
CFRelease(socketRunLoopSourceRef);
//Return success
return 0;
}
static void receiveData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
//CFSocketSendData(socket, address, (CFDataRef)data, 0.0);
CFDataRef buffer;
UInt8 *receivedData;
buffer = (CFDataRef)data;
CFDataGetBytes(
buffer,
CFRangeMake(0,CFDataGetLength(theData)),
&receivedData
);
//Show data received in label.
}
BOOL sendData: (void *)data{
CFSocketError socketErrors;
static char helloworld[] = "\r\nHello world";
CFDataRef _packet = CFDataCreate(NULL, (const UInt8 *)helloworld, strlen(helloworld));
socketErrors = CFSocketSendData(appSocket, NULL, packet, 0.0);
return;
}
@end
However, I still wasn't able to send data to my server. I am running a simple C-coded listening server on another machine to test my code.
Also, tried the AsyncUDPSocket library with much success. However, wanted to know the intricacies of the thing. The AsyncUDPSocket library gets and resolces IPv4 or IPv6 addresses. In my code for SocketTest, I am simply specifyinhg an IPv4 address.
So, my question refined is, why does this piece of code not work? Is there something very small, but very crucial that I am missing? Would appreciate any help on the same.
Thanks.