I am trying to get a program for iPhone running on the simulator. My problem is with receiving UDP data. I use asyncUdpSocket. If I make a socket and use sendData:(NSD
AsyncUdpSocket *socket=[[AsyncUdpSocket alloc]initWithDelegate:self];
//receiveWithTimeout is necessary or you won't receive anything
[socket receiveWithTimeout:-1 tag:2]; //-------here
NSData *data=[@"Hello from iPhone" dataUsingEncoding:NSUTF8StringEncoding];
[socket sendData:data toHost:bchost port:9003 withTimeout:-1 tag:1];
Not sure if this will be helpful, but I had the same problem, and here is how I fixed it.
In my case, the problem was that:
[self.socket receiveWithTimeout:-1 tag:0];
was located in the "wrong" place.
If you call [self.socket receiveWithTimeout:-1 tag:0]; in the method didFinishLaunchingWithOptions, the socket won't work regardless of what you do (even if you try launching it in a new thread). To fix this issue, I made a button and moved the receiveWithTimeout call to a method called when the button is clicked. My guess is that ASyncUdpSocket doesn't like something about the thread handling in didFinishLaunchingWithOptions.
I have posted my working sample code below (using XCode 5.1.1). These are the complete AppDelegate files for my Xcode project.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "AsyncUdpSocket.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate, AsyncUdpSocketDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) AsyncUdpSocket *udpSocket;
@property (strong, nonatomic) UILabel *receiver;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "AsyncUdpSocket.h"
#import <UIKit/UIKit.h>
#import <CFNetwork/CFNetwork.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create the main window
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
// Create a label for showing received text
self.receiver = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 80.0)];
self.receiver.text = @"No message, yet!";
self.receiver.textColor = [UIColor blackColor];
[self.window addSubview:self.receiver];
// Create a button for sending messages
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(80.0, 210.0, 160.0, 40.0)];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Start Game" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blueColor]];
[self.window addSubview:button];
@try {
self.udpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self];
if (![self.serverSocket bindToPort:9003 error:nil]) {
NSLog(@"COULD NOT BIND TO PORT");
}
if (![self.udpSocket enableBroadcast:YES error:nil]) {
NSLog(@"COULD NOT ENABLE BROADCASTING");
}
} @catch (NSException * e) {
NSLog(@"Exception: %@", e);
}
return YES;
}
- (void)buttonClick:(UIButton*)button {
NSData * data = [@"Hello World" dataUsingEncoding:NSUTF8StringEncoding];
[self.udpSocket receiveWithTimeout:-1 tag:0];
if (![self.udpSocket sendData:data toHost:@"127.0.0.1" port:9003 withTimeout:0.2 tag:1]) {
NSLog(@"COULD NOT SEND DATA");
} else {
NSLog(@"Sent packet (from %@:%d to 127.0.0.1:9001)", self.udpSocket.localHost, self.udpSocket.localPort);
}
}
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port {
NSLog(@" Received data (from %@:%d) - %@", host, port, data);
self.receiver.text = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self.udpSocket receiveWithTimeout:-1 tag:0];
return YES;
}
@end
Hope this is helpful to someone.
I'm new with Objective C (so bear with my ignorance of it), but I have been able to get AsyncUdpSocketDelegate to receive, for the most part. A few things to try/confirm:
Make sure the self
class that you are initializing as your socket delegate is the class that you're expecting the callbacks on.
Make sure your class adopts the AsyncUdpSocketDelegate
protocol. I'm not sure if this is actually necessary, but it couldn't hurt. In your class header, looks like:
@interface |your class| : |super class| <|Other protocol(s)|, AsyncUdpSocketDelegate> {
Make sure you have your delegate methods declared in your interface and implementation. The method signature should look like this:
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port;
Try calling receiveWithTimeout
with a non-zero timeout value. May give you different results.
Use Wireshark to make sure you are in fact receiving UDP data when and where you think you are. I'm not trying to insult your intelligence, but I've spent quite a while trying to track down network code bugs in the past when the issue was actually my network configuration.
I'm not familiar with this library but looking at the sample code from their Google Code Project reveals a few things.
First of, I don't see any mention of this callback you describe. Looks like you're supposed to implement:
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
Also in the example the server is started with the following line:
[listenSocket acceptOnPort:port error:&error]
Here's a link to the sample code.