开发iPAD应用程序,通过WiFi与UDP到串行转换器进行通信。应用程序以广播模式启动并检索响应单元列表(requestPodIds)。接收的数据将SN映射到单元IP地址。然后,所选的IP地址用于在iPad和UDP /串行转换器之间进行点对点通信。
我的代码在广播通信上运行良好。我向单元IP地址发送的单播消息(requestStatus)正由转换器接收,它正在按预期响应。但是,我没有将任何数据返回到didReceiveData方法。
我不明白为什么我没有在方法中获取数据:
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
我的套接字连接位于AppDelegate中,调用是来自viewController的模式。
Buttons on viewController are pressed as follows: 1. button1Click 2. button2Click; this calls requestPodIds; works fine; data returned which fills ten other button labels with pod ids; one is clicked;3. getPodIdsClick; this loads the IP address of the UDP/Serial converter;
4. getStatusClick; this is where the problem occurs. The UDP message goes out, the UDP converter receives the message and responds, I never see the response data in didReceiveData.
AppDelegate代码:
- (int) udpServiceStart {
NSError * UDPError;
if(GCDUdpSocket == nil)
{
GCDUdpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
}
GCDUdpSocket.delegate = self;
[GCDUdpSocket setIPv4Enabled:YES];
[GCDUdpSocket setIPv6Enabled:NO];
[GCDUdpSocket enableBroadcast:YES error:&UDPError];
if (![GCDUdpSocket bindToPort:udpPort error:&UDPError]) { NSLog(@"Error starting server (bind): %@", UDPError);
return -1;
}
if (![GCDUdpSocket beginReceiving:&UDPError])
// if (![GCDUdpSocket receiveOnce:&UDPError])
{
[GCDUdpSocket close];
NSLog(@"Error starting server (recv): %@", UDPError);
return -1;
}
NSLog(@"UDP Link started on port %hu", [GCDUdpSocket localPort]);
return 0;
}
- (void) connectToPodAtAddress: (NSString *) ipAddress
{
NSError * UDPError;
[GCDUdpSocket enableBroadcast:NO error:&UDPError];
podIp = ipAddress;
// if (![GCDUdpSocket connectToHost:podIp onPort:udpPort error:&UDPError])
// {
// [GCDUdpSocket close];
// NSLog(@"Error connecting to host: %@", UDPError);
// return;
// }
// if (![GCDUdpSocket beginReceiving:&UDPError])
// // if (![GCDUdpSocket receiveOnce:&UDPError])
// {
// [GCDUdpSocket close];
// NSLog(@"Error starting server (recv): %@", UDPError);
// return;
// }
}
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
fromAddress:(NSData *)address
withFilterContext:(id)filterContext
{
// NSError * UDPError;
NSString *msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (msg)
{
NSLog(@"RCV: %@", msg);
if(!commandBuffer) commandBuffer = [[NSMutableString alloc] initWithString:@""];
// Append the current message portion to the total message
[commandBuffer appendString:msg];
NSString * commands = [[NSString alloc] initWithString: commandBuffer];
NSInteger cr_index = [commands rangeOfString:@"\r"].location;
if([commands rangeOfString:@"\r"].location == NSNotFound)
{
if([commands rangeOfString:@"~~~ds"].location != NSNotFound)
{
[commandBuffer setString:@""];
}
} else {
[self decodeMessage:commands];
}
}
else
{
NSString *host = nil;
uint16_t thePort = 0;
[GCDAsyncUdpSocket getHost:&host port:&thePort fromAddress:address];
NSLog(@"Unknown message from : %@:%hu", host, thePort);
}
//
// Queue up to Read Next Message
//
// if (![GCDUdpSocket receiveOnce:&UDPError])
// {
// [GCDUdpSocket close];
// NSLog(@"Error starting server (recv): %@", UDPError);
// return;
// }
}
- (void)udpSendToHost:(NSString *)host onPort:(int) thePort theMessage: (NSString *) msg
{
NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
tag = 0;
[GCDUdpSocket sendData:data toHost:host port:thePort withTimeout:-1 tag:tag];
NSLog(@"SENT message for tag (%i) to host %@:%i", (int)tag, host, thePort);
NSLog(@"Message sent = (%@)", msg);
}
- (void) requestPodIds
{
#ifdef LOGFUNCTIONCALLS
NSLog(logString,__FUNCTION__);
#endif
[podTable removeAllObjects]; // pod_table.Clear(); // Empty table of any previous responses
if (GCDUdpSocket != nil) // null happens on startup if wireless adapter not found
{
// PodMessage to_pod = new PodMessage(PodCommands.ucget, PodParameters.serial_number);
PodMessage *to_pod = [[PodMessage alloc] initWithCommand:ucget andParams:serial_number];
// int bytes = udp_socket.SendTo(Encoding.ASCII.GetBytes(to_pod.Message()),
// new IPEndPoint(IPAddress.Broadcast, port));
[self udpSendToHost:podIp onPort:udpPort theMessage:to_pod.message];
// Debug.Assert(bytes == to_pod.Message().Length);
}
}
- (void) requestStatus
{
if (GCDUdpSocket != nil) // null happens on startup if wireless adapter not found
{
// PodMessage to_pod = new PodMessage(PodCommands.ucget, PodParameters.serial_number);
PodMessage *to_pod1 = [[PodMessage alloc] initWithCommand:ucget andParams:status_pod];
[self udpSendToHost:podIp onPort:udpPort theMessage:to_pod1.message];
// PodMessage *to_pod2 = [[PodMessage alloc] initWithCommand:ucget andParams:status_line0];
// [self udpSendToHost:podIp onPort:udpPort theMessage:to_pod2.message];
// PodMessage *to_pod3 = [[PodMessage alloc] initWithCommand:ucget andParams:status_line1];
// [self udpSendToHost:podIp onPort:udpPort theMessage:to_pod3.message];
// Debug.Assert(bytes == to_pod.Message().Length);
}
}
从ViewController访问如下:
wifiTestAppDelegate *appDelegate;
appDelegate = (wifiTestAppDelegate *)[[UIApplication sharedApplication] delegate];
- (IBAction)button1Click:(id)sender {
[appDelegate udpServiceStart];
}
- (IBAction)button2Click:(id)sender {
if([GCDUdpSocket isClosed])
{
NSLog(@"Socket is Closed!");
} else {
if([GCDUdpSocket isConnected])
{
NSLog(@"Socket is Connected! Can't Broadcast!");
} else {
[appDelegate requestPodIds];
}
}
}
- (IBAction)podSelectClick:(id)sender {
NSLog(@"Button with label %@",((UIButton *)sender).titleLabel.text);
NSLog(@"Button with tag %i",((UIButton *)sender).tag);
// UIButton *button = (UIButton *)[self.view viewWithTag:buttonTag++];
// [button setTitle:[podTable objectForKey:key] forState:UIControlStateNormal];
NSString * ipAddress = [podTable objectForKey:((UIButton *)sender).titleLabel.text];
NSLog(@"IP Address = %@",ipAddress);
podIp = ipAddress;
pod_sn = ((UIButton *)sender).titleLabel.text;
[appDelegate connectToPodAtAddress:ipAddress];
getStatusButton.hidden = NO;
[selectPodButton setTitle:ipAddress forState:UIControlStateNormal];
}
- (IBAction)getPodIdsClick:(id)sender {
int buttonTag = 101;
NSMutableArray * sortArray = [[NSMutableArray alloc] initWithCapacity:100];
if([podTable count] > 0)
{
for (NSString *key in podTable)
{
[sortArray addObject:key];
}
[sortArray sortUsingSelector:@selector(compare:)];
for(int i=0; i < [podTable count]; i++)
{
UIButton *button = (UIButton *)[self.view viewWithTag:buttonTag++];
[button setTitle:[sortArray objectAtIndex:i] forState:UIControlStateNormal];
}
}
}
- (IBAction)getStatusClick:(id)sender {
[appDelegate requestStatus];
}
答案 0 :(得分:0)
没有运气让GCDAsyncUdpSocket发送除了类广播之外的其他内容。解决了广播部分代码的BSD套接字解决方案的实现:
int fd;
int err;
int junk;
struct sockaddr_in addr;
NSData * data;
ssize_t bytesSent;
static const int kOne = 1;
fd = socket(AF_INET, SOCK_DGRAM, 0);
assert(fd >= 0);
err = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &kOne, sizeof(kOne));
assert(err == 0);
data = [@"hello" dataUsingEncoding:NSUTF8StringEncoding];
assert(data != nil);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_len = sizeof(addr);
addr.sin_port = htons(8023);
addr.sin_addr.s_addr = htonl(0xffffffff); // 255.255.255.255
bytesSent = sendto(fd, [data bytes], [data length], 0, (const struct sockaddr *) &addr, sizeof(addr));
NSLog(@"bytes sent = %zd", bytesSent);
junk = close(fd);
assert(junk == 0);