Ho fatto qualche ricerca su google e qualche lettura su questo argomento, ma non riesco a farlo bene, non importa quanto tempo ho passato a cercare.Trasmissione UDP tramite CFSocket su IOS
Quello che voglio fare è ricevere messaggi broadcast di dispositivi che sono collegati sulla mia rete pubblicizzando il mio interesse nei loro servizi che forniscono. Usando wireshark posso vedere i messaggi broadcast/di notifica dai dispositivi di rete che voglio connettere a inviati sulla mia rete ma non la mia ricerca in broadcast per interesse dei loro servizi. Ma con l'utilità di rete posso vedere che il socket è stato creato ma non so in quale stato si trova, se ascoltato o connesso.
Sì, so che ci sono librerie che posso usare per fare questo, ma volevo costruire qualcosa di mio da zero e capire meglio come funziona.
MySocket.h
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#if TARGET_OS_IPHONE
#import <CFNetwork/CFNetwork.h>
#endif
@interface MySocket : NSObject
{
NSString* _message;
CFSocketRef cfSocket;
CFRunLoopSourceRef cfSource;
}
- (void)listen;
@end
MySocket.m
#import "MySocket.h"
#define MAX_UDP_DATAGRAM_SIZE 65507
@implementation MySocket
static void socketCallback(CFSocketRef cfSocket, CFSocketCallBackType
type, CFDataRef address, const void *data, void *userInfo)
{
NSLog(@"socketCAllBAck was called");
}
- (void)listen
{
//Enable broadcast to network hosts
int yes = 1;
int setSockResult = 0;
_message = [[NSMutableString alloc ] initWithString: @"M-SEARCH *HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:1\r\n\r\n"];
CFSocketContext socketContext = {0, self, NULL, NULL, NULL};
/* Create the server socket as a UDP IPv4 socket and set a callback */
/* for calls to the socket's lower-level accept() function */
cfSocket = CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP,
kCFSocketAcceptCallBack | kCFSocketDataCallBack , (CFSocketCallBack)socketCallback, &socketContext);
if (cfSocket == NULL)
NSLog(@"UDP socket could not be created\n");
/* Re-use local addresses, if they're still in TIME_WAIT */
setSockResult = setsockopt(CFSocketGetNative(cfSocket), SOL_SOCKET, SO_BROADCAST, (void *)&yes, sizeof(yes));
if(setSockResult < 0)
NSLog(@"Could not setsockopt for broabcast");
/* Set the port and address we want to listen on */
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("239.255.255.250");
//inet_pton(AF_INET, "239.255.255.250", &(addr.sin_addr));
addr.sin_port = htons(1900);
//addr.sin_addr.s_addr = htonl(INADDR_ANY);
NSData *address = [ NSData dataWithBytes: &addr length: sizeof(addr) ];
if (address != nil && CFSocketSetAddress(cfSocket, (CFDataRef) address) != kCFSocketSuccess) {
NSLog(@"CFSocketSetAddress() failed\n");
CFRelease(cfSocket);
}
CFDataRef data = CFDataCreate(NULL, (const UInt8*)[_message UTF8String], [_message lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
setSockResult = CFSocketSendData(cfSocket, (CFDataRef)address, data, 0.0);
if(kCFSocketSuccess != setSockResult) NSLog(@"Unable to send data, %i", setSockResult);
else NSLog(@"Sending data");
cfSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, 0);
if(cfSource == NULL)
NSLog(@"CFRunLoopSourceRef is null");
CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
NSLog(@"Socket listening on port 1900");
CFRelease(cfSource);
CFRelease(cfSocket);
[address release];
data = nil;
CFRunLoopRun();
}
- (void)dealloc
{
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
CFRelease(cfSource);
CFRelease(cfSocket);
[_message release];
[super dealloc];
}
@end
Edit: Tutto funziona bene fino a quando la chiamata per inviare i dati.
C'è qualcosa di piccolo ma fondamentale per far funzionare tutto ciò che mi manca? O mi manca l'immagine grande?
Qualsiasi aiuto o guida è apprezzato. Grazie in anticipo e hanno un bel weekend