在LAN中广播UDP消息以检测IP摄像机

时间:2014-01-15 13:20:58

标签: ios networking

我正在尝试为我的iPhone构建一个小程序,它允许检测本地网络上的设备(尤其是IP摄像机)。我知道其中一些像UPnP和我这样的支持协议也一直在玩这个,但我现在想要完全实现我的iPhone和相机之间的通信而不依赖于库。

我的方法是将广播消息发送到本地网络并解析收到的响应。例如,为了检测本地网络上的UPnP设备,广播的消息需要具有以下内容:

M-SEARCH * HTTP/1.1\r\nHOST:255.255.255.255:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:1\r\n\r\n

我对C语言中的网络编程有点熟悉,所以我想用C语言编写通信代码,然后在我的Objective-C中集成。

我目前正在做以下事情:

// Create socket
int sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

// Enable broadcast messaging
int broadcastEnable = 1;
int ret = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));

// Configure the port and ip we want to send to
struct sockaddr_in broadcastAddr; // Make an endpoint
memset(&broadcastAddr, 0, sizeof broadcastAddr);
broadcastAddr.sin_family = AF_INET;
inet_pton(AF_INET, "255.255.255.255", &broadcastAddr.sin_addr); // Set the broadcast IP address
broadcastAddr.sin_port = htons(1900); // Set port 1900

// Create the broadcast UPnP request
char *request = "M-SEARCH * HTTP/1.1\r\nHOST:255.255.255.255:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:1\r\n\r\n";

// start the broadcast
success = sendto(sd, request, strlen(request), 0, (struct sockaddr*)&broadcastAddr, sizeof broadcastAddr);

现在,我陷入困境,因为我不知道如何处理任何答案。 UPnP设备的回复是否会在同一个套接字上进行?我相信它应该能够通过recv()recv()接收传入的回复,但我不确定如何实现它们。我是否必须创建一个新套接字,或者我可以只创建现有套接字?是否必须使用bind()?

绑定套接字

1 个答案:

答案 0 :(得分:4)

首先,您正在尝试为服务发现发送SSDP数据包。所以你应该把这个数据包发送到多播地址239.255.255.250而不是255.255.255.255。

除此之外,您还可以在同一个套接字上收到对发现请求的响应。只需在此套接字上调用recv()函数即可。

此外,我希望您使用的是Mac OS X(正在为iOS开发),因此您已经安装了Python。只需打开终端并输入 python ,然后按照python代码复制粘贴,

import sys
import socket

SSDP_ADDR = "239.255.255.250";
SSDP_PORT = 1900;
SSDP_MX = 1;
SSDP_ST = "ssdp:all";

ssdpRequest = "M-SEARCH * HTTP/1.1\r\n" + \
                "HOST: %s:%d\r\n" % (SSDP_ADDR, SSDP_PORT) + \
                "MAN: \"ssdp:discover\"\r\n" + \
                "MX: %d\r\n" % (SSDP_MX, ) + \
                "ST: %s\r\n" % (SSDP_ST, ) + "\r\n";

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT))
print sock.recv(1000)

此代码将发送一个发现数据包,并将打印它从网络接收的第一个响应。我只是分享这段代码,因为即使你不懂python也可以轻松测试并理解代码。当然,这可以很容易地翻译成C.

我希望它有所帮助。