iPhone 上不发送 UDP 数据包

Posted

技术标签:

【中文标题】iPhone 上不发送 UDP 数据包【英文标题】:UDP packets are not sent on the iPhone 【发布时间】:2012-03-25 15:13:51 【问题描述】:

我使用这个库:https://github.com/robbiehanson/CocoaAsyncSocket

我的测试代码:

#import <UIKit/UIKit.h>
@class GCDAsyncUdpSocket;

@interface ThirdViewController : UIViewController

    GCDAsyncUdpSocket *udpSocket;

.m:

#import "ThirdViewController.h"
#import "DDLog.h"
#import "DDTTYLogger.h"
#import "GCDAsyncUdpSocket.h"
static const int ddLogLevel = LOG_LEVEL_VERBOSE;

@implementation ThirdViewController
- (void)viewDidLoad

    [super viewDidLoad];
    [DDLog addLogger:[DDTTYLogger sharedInstance]];
    udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

    [udpSocket bindToPort:7744 error:nil];
    [udpSocket beginReceiving:nil];
    [udpSocket enableBroadcast:YES error:nil];
    //[udpSocket connectToHost:@"127.0.0.1" onPort:55544 error:nil];

    NSData *data = [@"test" dataUsingEncoding:NSUTF8StringEncoding];

    //[udpSocket sendData:data withTimeout:-1 tag:0];
    [udpSocket sendData:data toHost:@"127.0.0.1" port:55544 withTimeout:-1 tag:0];

但是包裹没有寄出。我使用了这个数据包嗅探器:http://sourceforge.net/projects/packetpeeper/

在库中有一个客户端示例(适用于 Mac),我看到了他的包。我尝试在真实设备上运行该应用程序,但也没有发送任何内容(地址当然是另一个)。有什么问题?

【问题讨论】:

【参考方案1】:

您正在侦听端口 7744 并且正在传输到端口 55544。您应该传输到与您正在收听的端口相同的端口。即发送应该是:

[udpSocket sendData:data toHost:@"127.0.0.1" port:7744 withTimeout:-1 tag:0];

对 packetkeeper 看不到数据包的原因的有根据的猜测是因为它们没有从任何网络接口出去 - 这是一个一般的优化,lo 设备 (127.0.0.1) 的数据包不出去电线;他们只是在本地循环。大多数数据包拦截设备无法检测到这种类型的数据包。

编辑您至少需要两个GDCAsyncUdpSockets - 一个用于客户端,一个用于服务器。实现这一点的最简单方法是拥有两个独立的应用程序,一个作为服务器运行,另一个作为客户端运行。

这个 ThirdViewController 是某种形式的 UDP 客户端。当您发出bindToPort 时,您需要使用端口号0,这会导致操作系统为此系统分配一个用于监听的端口。如果您想接收从服务器发送的数据包,则需要这样做。

[udpSocket bindToPort:0 error:nil];

顺便说一句,我总是会检查 bindToPort 上的错误。

在服务器端,需要绑定一个已知端口:

[serverSocket bindToPort:55544 error:nil];

在客户端,当你发送消息时你需要做的(对于模拟器):

[udpSocket sendData:data toHost:@"127.0.0.1" port:55544 withTimeout:-1 tag:0];

在服务器端,当您在didReceiveData 处理程序中收到消息时,您会收到一个fromAddress。这个地址对应来自udpSocket的地址和端口,如果要回传消息给客户端,可以使用:

[serverSocket sendData:data toAddress:fromAddress withTimeout:-1 tag:0];

当我遵循这种方法时,我可以毫无困难地从udpSocketserverSocket 发送数据包并处理响应。我在 Mac 端使用 wireshark 来查看来自 iDevice 的数据包。当我使用模拟器时,我发送到 127.0.0.1 并在服务器上看到了响应。

【讨论】:

感谢您的回答!我改变了相同的监听端口,在哪个传输。我曾尝试在 eth1 上发送,但我还是没有看到包裹。我看到的mac应用发送的包,即使地址是127.0.0.1 如何确定要使用的toHost 地址?您输入的屏幕上是否有 iDevice 的 IP 地址,因为这是您必须使用的地址,除非您使用广播地址 - 如果您的桌面位于 192.168.1.5,则广播地址为 192.168.1.255。您可以通过Network Preferences Pane 确定您桌面的 IP 地址。 我的电脑连接到路由器,地址为192.168.10.101。当我尝试从 iDevice 发送数据包时,我选择此地址为toHost。 IDevice 的地址为192.168.10.102。当我尝试从模拟器发送时,我选择地址127.0.0.1。我也尝试选择192.168.10.101。我设置的 enableBroadcast 是NO 我在答案中添加了更多细节 - 您正在运行服务器套接字来查看来自客户端的消息?客户端不应绑定到特定端口 - 它应该使用 0 随机选择一个端口。服务器套接字应绑定到特定端口,客户端应发送到该指定端口。 我都这样做了。我的错误在另一个,现在我找到了。非常感谢您关注我的问题!

以上是关于iPhone 上不发送 UDP 数据包的主要内容,如果未能解决你的问题,请参考以下文章

网吧局域网内机器发送udp数据包问题

为啥 traceroute 发送 UDP 数据包而不是 ICMP 数据包?

收发UDP数据包

Linux内核网络UDP数据包发送——Linux netdevice 子系统

Linux内核网络UDP数据包发送——Linux netdevice 子系统

为啥 Java DatagramSocket 没有收到客户端发送的所有 udp 数据包?