UDP Multicast

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Slaxx
User
Beiträge: 6
Registriert: Donnerstag 12. März 2015, 13:52

Hallo zusammen
Ich versuche Multicast in Python zum Laufen zu bringen. Ich habe im Internet diverse Code Schnipsel gefunden aber leider funktioniert nichts.
Zuerst habe ich das ganze mal in C++ versucht. Nach mehrstündigem testen habe ich es so zum laufen gebracht:

Code: Alles auswählen

//Client: receive messages

#include<stdio.h>
#include<winsock2.h>
#include<Ws2tcpip.h>
 
#pragma comment(lib,"ws2_32.lib") //Winsock Library
 
#define BUFLEN 65467  //Max length of buffer
#define PORT 49972  //The port on which to listen for incoming data

int main()
{
    SOCKET s;
    struct sockaddr_in server, si_other;
	struct ip_mreq multicast_group;

    int slen , recv_len;
    char buf[BUFLEN];
    WSADATA wsa;
 
    slen = sizeof(si_other) ;
     
    //Initialise winsock
    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        printf("Failed. Error Code : %d",WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    printf("Initialised.\n");
     
    //Create a socket
    if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
    {
        printf("Could not create socket : %d" , WSAGetLastError());
    }
    printf("Socket created.\n");
     
    //Prepare the sockaddr_in structure
	memset((char *) &server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( PORT );

     
    //Bind
    if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
    {
        printf("Bind failed with error code : %d \n" , WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    puts("Bind done");


	multicast_group.imr_multiaddr.s_addr = inet_addr("239.132.79.4"); //group adress
	multicast_group.imr_interface.s_addr = inet_addr("127.0.0.1"); //ip adress from server
	setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multicast_group, sizeof(multicast_group));

    //keep listening for data
    while(1)
    {
        printf("Waiting for data...");
        fflush(stdout);
         
        //clear the buffer by filling null, it might have previously received data
        memset(buf,'\0', BUFLEN);
         
        //try to receive some data, this is a blocking call
        if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
        {
            printf("recvfrom() failed with error code : %d" , WSAGetLastError());
            exit(EXIT_FAILURE);
        }
         
        //print details of the client/peer and the data received
        printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
        printf("Data: %s\n" , buf);
         
        //now reply the client with the same data
        /*if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
        {
            printf("sendto() failed with error code : %d" , WSAGetLastError());
            exit(EXIT_FAILURE);
        }*/
    }
 
    closesocket(s);
    WSACleanup();
     
    return 0;
}
Entscheidend waren die 3 Zeilen:

Code: Alles auswählen

	multicast_group.imr_multiaddr.s_addr = inet_addr("239.132.79.4"); //group adress
	multicast_group.imr_interface.s_addr = inet_addr("127.0.0.1"); //ip adress from server
	setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multicast_group, sizeof(multicast_group));
Mein Python Code sieht folgendermassen aus:

Code: Alles auswählen

import socket
import struct
import sys

multicast_group = '239.132.79.4'
server_address = ('', 49972)

# Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind to the server address
sock.bind(server_address)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(10)

# Tell the operating system to add the socket to the multicast group
# on all interfaces.
group = socket.inet_aton(multicast_group)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

# Receive/respond loop
while True:
    print >>sys.stderr, '\nwaiting to receive message'
    data, address = sock.recvfrom(65467)
    
    print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
    print >>sys.stderr, data

    print >>sys.stderr, 'sending acknowledgement to', address
    sock.sendto('ack', address)
Ich nehme an, dass mir irgendwelche Einstellungen fehlen, ich weiss aber nicht welche genau.
Wer kann mir helfen?
BlackJack

@Slaxx: Die besagten Zeilen im C++-Programm sehen in Python irgendwie anders aus. Die ``ip_mreqn``-Struktur enthält *zwei* Adressen und ein ``int``. In Python packst Du da *eine* Adresse und ein ``long``. Das erste `struct.pack()`-Argument müsste also eher '4s4si' sein.
Slaxx
User
Beiträge: 6
Registriert: Donnerstag 12. März 2015, 13:52

Wenn ich das ändere erscheint eine Fehlermeldung.
Mittlerweile läuft es allerdings zwischendurch und zwischendurch wieder nicht. Scheint recht komisch zu sein.
Wenn ich vorher ein C++ Receiver starte und dann das Python Programm funzts. Starte ich aber das python programm direkt kommt nichts an.
Irgendwie scheint es, also ob das Python Programm den Port nicht selber freimachen könnte oder so...
Antworten