2014-12-23 3 views
0

UDP를 사용하는 장치와 통신하는 iOS 앱을 작성하려고합니다. 장치 설명서에는 특정 IP 주소 (224.4.0.1)와 특정 포트 번호로 통신한다고되어 있습니다.특정 IP 주소로 UDP 사용하기

특정 IP 주소로 UDP 패킷을 보내고받는 올바른 방법을 찾아내는 데 어려움을 겪고 있습니다. 이것은 가능한가?

하나의 IOS 장치에서 UDP 패킷을 보내고 다른 장치에서 UDP 패킷을 수신 할 수있는 테스트 코드를 작성했습니다. 내가 작성한 코드는 보내는 IP 주소를 INADDR_BROADCAST로 지정하고받는 주소를 INADDR_ANY로 지정하는 한 작동합니다. 224.4.0.1 주소로 둘 중 하나 또는 모두를 변경하자마자 더 이상 작동하지 않습니다 (송신자는 오류를보고하지 않지만 수신자는 패킷을받지 못합니다).

224.4.0.1은 멀티 캐스트를 위해 예약 된 IP 주소의 범위 내에 있음을 이해합니다. 바인딩하기 전에 수신 대기 소켓에 SO_REUSEADDR 옵션을 설정해야합니다.

내가 궁극적으로 사용하려고하는 장치는 내 네트워크에 있지만 지금까지 전송하려는 모든 것에 응답하지 않았습니다. 기기의 특성에 대해 걱정하기 전에 두 개의 iPhone으로 테스트 케이스를 작성하고 싶습니다.

저는 버클리 소켓을 직접 사용하거나 CFSocket으로 포장하고 있습니다. 필자는 이전 프로젝트에서 TCP와 인터페이스를 성공적으로 사용 했으므로 전반적인 작동 방법에 상당히 익숙합니다.

struct sockaddr_in sin_send; 
    memset(&sin_send, 0, sizeof(sin_send)); 
    sin_send.sin_len = sizeof(sin_send); 
    sin_send.sin_family = AF_INET; 
    sin_send.sin_port = htons(PORT_SEND); 
    //sin_send.sin_addr.s_addr = htonl(INADDR_BROADCAST); 
    inet_aton([@"224.4.0.1" UTF8String], &sin_send.sin_addr); 

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    int reuse = 1; 
    NSLog(@"reuse %d", setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse))); 
    NSLog(@"connect %d", connect(sock, (const struct sockaddr *) &sin_send, sizeof(sin_send))); 

    _sendSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sock, kCFSocketWriteCallBack, socketWriteCallBack, &context); 

    if (!CFSocketIsValid(_sendSocket)) { 
     NSLog(@"Send socket is not valid"); 
     return; 
    } 

    // Disable "nagling" 
    CFSocketNativeHandle ssock = CFSocketGetNative(_sendSocket); 
    int i = -1; 
    setsockopt(ssock, IPPROTO_TCP, TCP_NODELAY, (char*) &i, sizeof(int)); 

    // Enable broadcast 
    int broadcast = 1; 
    setsockopt(ssock, SOL_SOCKET, SO_BROADCAST, (char*) &broadcast, sizeof(int)); 

이는 수신 소켓입니다 : 여기

가 전송 소켓을 설정하는 코드이다

struct sockaddr_in sin_read; 
    memset(&sin_read, 0, sizeof(sin_read)); 
    sin_read.sin_len = sizeof(sin_read); 
    sin_read.sin_family = AF_INET; 
    sin_read.sin_port = htons(PORT_READ); 
    //sin_read.sin_addr.s_addr = INADDR_ANY; 
    inet_aton([@"224.4.0.1" UTF8String], &sin_read.sin_addr); 

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    int reuse = 1; 
    NSLog(@"reuse %d", setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse))); 
    NSLog(@"bind %d", bind(sock, (const struct sockaddr *) &sin_read, sizeof(sin_read))); 

    int broadcast = 1; 
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*) &broadcast, sizeof(int)); 

    int flags; 
    flags = fcntl(sock, F_GETFL); 
    NSLog(@"fcntl %d", fcntl(sock, F_SETFL, flags | O_NONBLOCK)); 

    _readSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sock, kCFSocketAcceptCallBack | kCFSocketDataCallBack | kCFSocketReadCallBack, socketReadCallBack, &context); 

감사합니다, 프랭크

+1

일부 코드 스 니펫을 게시 할 수 있다면 많은 도움이됩니다. – chancyWu

+0

통신에 관련된 두 개의 주소, 즉 보낸 사람 (귀하)과 수신자 (장치)가 있습니다. 이 기기는 멀티 캐스트 주소 224.4.0.1에서 수신 대기 중입니다. 대상 IP 주소로 설정해야합니다. IP 주소는 멀티 캐스트 주소 일 필요는 없습니다. 실제로는 안된다. 원본 IP 주소에 대해 INADDR_ANY이 (가) 올바른 것입니다. – Paulw11

+0

또한 CocoaAsyncSocket에서 GCDAsyncSocket과 같은 라이브러리를 사용하는 것이 훨씬 간단하다는 것을 알 수 있습니다. 예를 들어,이 답변에서 "Server"(실제로 "보낸 사람"이어야 함) 코드를 참조하십시오. -http : //stackoverflow.com/questions/ 11621553/how-to-use-gcdasyncudpsocket-for-multicast-over-wifi-and-bluetooth – Paulw11

답변

1

이 솔루션은 내 청취 소켓을 결합했다 를 INADDR_ANY로 설정 한 다음 setsockopt와 IP_ADD_MEMBERSHIP 옵션을 사용하여 원하는 IP 주소를 수신하는지 확인하십시오.

struct ip_mreq mreq; 
    memset(&mreq, 0, sizeof(mreq)); 
    inet_aton([@"224.4.0.1" UTF8String], &mreq.imr_multiaddr); 
    mreq.imr_interface.s_addr = INADDR_ANY; 
    setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); 
관련 문제