Shoutcast senden



  • okay, das ist jetzt schonmal übersichtlicher. also da du wohl noch nicht viel mit sockets gemacht hast kann ich dir gleich sagen, dass senden und empfangen von streams nicht grade einfach ist, da du ja auf der untersten ebene mit den sockets arbeitest (außer raw).

    was du aufjedenfall bruachen wirst sind threads und ein fifo-puffer.

    ich werde mir den code jetzt dann nochmal anschaun..

    edit: also ich hab den code mal angeschaut und auch etwas geändert und zwei kommentare dazu geschrieben die du mir erklären solltest..

    #include <iostream>
    
    #include <fcntl.h>
    
    #include <sys/types.h>
    
    #include <sys/socket.h>
    
    #include <netdb.h>
    
    #include <netinet/in.h>
    
    #include <arpa/inet.h>
    
    #define BUFFER_SIZE 32
    
    #define LISTENPORT 8007
    
    #define LINEBUFFERING 1
    
    using namespace std;
    
    int onair = 0;
    
    int Casting (int c)
    
    {
    
        int sc, scbytes, sendet, recvit;
    
        struct sockaddr_in scaddr;
    
        socklen_t client_size;
    
        char buffer[32], scbuffer[32], pw[32];
    
        sc = socket(AF_INET, SOCK_STREAM, 0);
    
    	memset(&scaddr, 0, sizeof(struct sockaddr_in));
    
        scaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
        scaddr.sin_port = htons(8061);
    
        scaddr.sin_family = AF_INET;
    
        //setsockopt(sc, SOL_SOCKET, SO_SNDTIMEO, (const char *)10000, 5);
    
        //setsockopt(sc, SOL_SOCKET, SO_RCVTIMEO, (const char *)10000, 5);
    
        if (connect(sc, (struct sockaddr*)&scaddr, sizeof(scaddr)) == -1)
    
        {
    
    	  cout << "Cannot connect to Shoutcast! ";
    
        }
    
        else
    
        {
    
    	  char buffer_recv[1024];  // wird nicht verwedent ?
    
    	  char sc_buffer[1024], c_buffer[1024];
    
    	  while(true)
    
    	  {	
    
    	    cout << "Datas:\n------\n";
    
        	recv(c, &sc_buffer, sizeof(sc_buffer), MSG_WAITALL);
    
    	    recv(sc, &c_buffer, sizeof(c_buffer), MSG_WAITALL);
    
    	    cout << "Length of buffer from Client: " << strlen(sc_buffer) << "; Value: " << sc_buffer << "\nLength of buffer from Server: " << strlen(c_buffer) << "; Value: " << c_buffer << "\n\n";
    
    	    if (strlen(sc_buffer) < 0)  // gibt die funktion überhaupt mal ein wert kleiner als 0 ?
    
    	    {
    
    		  break;
    
    	    }   
    
    	    send(sc, sc_buffer, strlen(sc_buffer), 0);
    
    	    send(c, c_buffer, strlen(c_buffer), 0);  
    
    /*
    
    	    sc_buffer[0] = 0;
    
    	    c_buffer[0] = 0;
    */
    
    		strcpy(sc_buffer, "");
    		strcpy(c_buffer, "");
    
    	  }
    
        }
    
        cout << "Loose Connection!\n";
    
        close(c);
    
        close(sc);
    
        system("cd /root/playlist; ./sc_trans &");
    
        cout << "Started sc_trans\n";
    
        onair = 0;
    
        return 0;
    
    }
    
    int main()
    
    {
    
        int s, c, scbytes;
    
        struct sockaddr_in sockAddr1, client;
    
        socklen_t client_size;    
    
        s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        if (s < 0)
    
        {
    
    	  cout << "No Socket\n";
    
        }
    
        else
    
        {	
    
    	  cout << "Listening to Port ... Please wait!\n";
    
    	  memset(&sockAddr1, 0, sizeof(struct sockaddr_in));
    
    	  sockAddr1.sin_family = AF_INET;
    
    	  sockAddr1.sin_port = htons(LISTENPORT);
    
    	  sockAddr1.sin_addr.s_addr = INADDR_ANY;
    
    	  if (bind(s, (struct sockaddr*)&sockAddr1, sizeof(sockAddr1)) == -1)
    
    	  {
    
    	    cout << "Error binding\n";
    
    	  }
    
    	  else
    
    	  {
    
    	    if (listen(s, 5) == -1)
    
    	    {
    
    		  cout << "Cannot Listening\n";
    
    	    }
    
    	    else
    
    	    {
    
    		  while(true)
    
    		  {
    
    		    client_size = sizeof(client);
    
    		    c = accept(s, (struct sockaddr*)&client, &client_size);
    
    		    if (c == -1)
    
    		    {
    
    			  cout << "Cannot Accept\n";
    
    		    }
    
    		    else
    
    		    {
    
    			  cout << "Accpeted: " << inet_ntoa(client.sin_addr) << ":" << ntohs(client.sin_port) << "\n";
    
    			  if (onair == 1)
    
    			  {
    
    			    send(c, "Leider ist der Stream bereits besetzt.", 38, 0);
    
    			    cout << "Sorry Message sendet\n";
    
    			  }
    
    			  if (onair == 0)
    
    			  {
    
    			    onair = 1;
    
    			    system("killall -KILL sc_trans ");
    
    			    cout << "Killed sc_trans\n\n";
    
    			    Casting(c);
    
    			    onair = 0;
    
    			  }
    
    		    }
    
    		  }
    
    		}
    
    	  }
    
        }
    
      close(s);
    
    }
    

    ich kann den code allerdings nur durch den compiler jagen und schaun ob codefehler drin sind und ihn nicht testen - wäre gut wenn du ein client programmieren würdest der alle funktionen testet.

    mfg blan



  • zu den beiden kommentaren.

    1. ich hatte viele versionen des quelltextes, darum wurde das 1. vergessen...

    2. ja sollte, sobald ein fehler besteht also wenn der client off ist ...

    nunja ich hab das ganze ausprobiert auch noch editiert hat aber nichts gebracht... was ich festgestellt hab ist, das es eigentlich nichts vom shoutcast server empfangen kann... d.,h. die schleife wird solang nicht ausgeführt, wie keine daten vom shoutcast kommen, bis nach etwa 30 sek, dann wird das warten abgebrochen und es wird neu empfangen... nehm ich das empfangen vom shoutcast server raus (also // vorne hin), so kann die erste schleiffe innert sekunden bruchteilen ausgeführt werden, der 2. vorgang dann auch nicht mehr, da keine daten mehr vom client kommen. evt bringt dir das etwas...

    vielen dank

    mfg

    xstream



  • versteh ich nicht ganz... dir ist schonklar, das die funktionen "accept" und "recv" blockieren und es nicht weitergeht wenn er keine daten empfängt und das geht unendlich lang so... d.h wenn du keine daten reinbekommst wird die main-schleife auch nicht weiterlaufen... sowas must du mit threads machen - hab ich aber oben schonmal geschrieben.

    p.s: nochmal erklären wenn ich dein post nicht verstanden habe

    mfg blan



  • es geht solang nicht weiter, wie er keine daten empfängt?

    kann man das nicht irgendwie unterbinden, ohne threads?

    oder gibt es irgendwo ein einfaches thread-tutorial oder ein beispiel, das an mein problem hinkommt mit threads?

    wäre sehr froh.

    mfg

    xstream



  • unter linux benutzt man doch auch gerne mal qt:

    QSocket::readyRead()
    

    informiert dich darueber, dass daten angekommen sind.



  • nein ohne threads wirds des net hinbekommen, jedenfalls net wirklich... vll mit polling oder sowas aber machs ambesten mit pthreads oder boost library, einfach bischen googeln. sind bei deinen sachen egtl nurn paar zeilen coden...

    mfg blan



  • okey vielen dank... werd mich dran machen. bei weiteren problemen werd ich einfach das mal wieder hier hineinwerfen.

    mfg

    xstream



  • Die Stichworte sind fnctl mit O_NONBLOCK und select/poll. Skalieren nicht besonders gut aber für wenige Verbindungen eignet sich das ganz hervorragend für nicht-blockierende Socketoperationen ohne Threads.

    xstream schrieb:

    2. ja sollte, sobald ein fehler besteht also wenn der client off ist ...

    😕 Dir ist nicht klar dass strlen herzlich wenig mit dem Client oder Fehlern bei der Übertragung am Hut hat, oder?

    EDIT:
    Um die letzte Äusserung etwas zu erweitern: Der Rückgabewert von recv ist hier ausschlaggebend, nicht der von strlen, der ist immer > 0 (allein schon weil der Rückgabetyp unsigned ist). Und auch hier sind "Fehler" und "Client hat Verbindung geschlossen" nicht äquivalent, denn wenn recv 0 zurückgibt heisst das, dass der Client die schreibseitige Verbindung geschlossen hat, und wenn recv -1 zurückgibt heisst das, dass ein Fehler (Netzwerk zusammengebrochen, Ressourcen erschöpft, whatsoever) aufgetreten ist.



  • ja das stimmt. tut mir leid, daran hab ich nciht gedacht.

    ich werde die beiden stichwörter testen. danke

    mfg

    xstream



  • guten tag

    ich hab nun das fnctl ausprobiert. funktioniert auch, auch das das gesammte passwort nun an den server übermittelt wird, nun meldet aber recv vom shoutcast server, also dort wo das ganze hin soll:

    errno: 11
    error: Resource temporarily unavailable

    kann mir darauf noch jemand ne lösung sagen? wäre sehr sehr froh.

    mfg

    xstream



  • wer gibt diese meldung aus und wo ? (der shoutcast-server ?)

    mfg blan



  • mein programm mit der funktion strerror();

    die nummer ist in errno nach dem recv() zum shoutcast server.

    mfg

    xstream



  • ist der rückgabewert von recv überhaupt -1?



  • ja der rückgabe wert ist -1...



  • gib mal den code...

    mfg blan



  • #include <iostream>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    
    #define BUFFER_SIZE 32
    #define LISTENPORT 8016
    #define LINEBUFFERING 1
    
    using namespace std;
    
    int onair = 0;
    
    int Casting (int c)
    {
        int sc, scbytes, sendet, recvit;
        struct sockaddr_in scaddr;
        socklen_t client_size;
    
        sc = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        scaddr.sin_addr.s_addr = inet_addr("85.25.90.52");
        scaddr.sin_port = htons(8061);
        scaddr.sin_family = AF_INET;
    
        //setsockopt(sc, SOL_SOCKET, SO_SNDTIMEO, (const char *)10000, 5);
        //setsockopt(sc, SOL_SOCKET, SO_RCVTIMEO, (const char *)10000, 5);
    
        if (connect(sc, (struct sockaddr*)&scaddr, sizeof(scaddr)) == -1)
        {
    	cout << "Cannot connect to Shoutcast! " << errno;
        }
        else
        {
    
    	char sc_buffer[1024], c_buffer[1024];
    
    	fcntl(sc, F_SETFL, O_NONBLOCK);
    
    	int answer_c, answer_sc;
    
    	while (true)
    	{	
    	    cout << "Datas:\n------\n";
    
        	    answer_c = recv(c, sc_buffer, strlen(sc_buffer), 0);
    	    sc_buffer[answer_c] = '\0';
    	    send(sc, sc_buffer, strlen(sc_buffer), 0);
    
    	    answer_sc = recv(sc, c_buffer, strlen(c_buffer), 0);
    	    c_buffer[answer_sc] = '\0';
    	    send(c, c_buffer, strlen(c_buffer), 0);
    
    	    cout << answer_c << " .. " << answer_sc << "..";
    	    cout << strerror(errno) << "Length of buffer from Client: " << strlen(sc_buffer) << "; Value: " << sc_buffer << "(" << answer_c << ")" << "\nLength of buffer from Server: " << strlen(c_buffer) << "; Value: " << c_buffer << "(" << answer_sc << ")" << "\n\n";
    
    	    if (answer_c < 0 || answer_sc < 0)
    	    {
    		break;
    	    }   
    
    	    sc_buffer[0] = 0;
    	    c_buffer[0] = 0;
    	}
        }
    
        cout << "Loose Connection!\n";
    
        close(c);
        close(sc);
    
        //system("cd /root/playlist; ./sc_trans &");
    
        cout << "Started sc_trans\n";
    
        onair = 0;
        return 0;
    }
    
    int main()
    {
        int s, c, scbytes;
        struct sockaddr_in sockAddr1, client;
        socklen_t client_size;    
    
        s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
        //fcntl(s, F_SETFL, O_NONBLOCK);
    
        if (s < 0)
        {
    	cout << "No Socket\n";
        }
        else
        {	
    	cout << "Listening to Port ... Please wait!\n";
    	sockAddr1.sin_family = AF_INET;
    	sockAddr1.sin_port = htons(LISTENPORT);
    	sockAddr1.sin_addr.s_addr = INADDR_ANY;
    
    	if (bind(s, (struct sockaddr*)&sockAddr1, sizeof(sockAddr1)) == -1)
    	{
    	    cout << "Error binding\n";
    	}
    	else
    	{
    	    if (listen(s, 5) == -1)
    	    {
    		cout << "Cannot Listening\n";
    	    }
    	    else
    	    {
    
    		for (;;)
    		{
    		    client_size = sizeof(client);
    		    c = accept(s, (struct sockaddr*)&client, &client_size);
    
    			if (c == -1)
    			{
    			    cout << "Cannot Accept\n";
    			}
    			else
    			{
    			    cout << "Accpeted: " << inet_ntoa(client.sin_addr) << ":" << ntohs(client.sin_port) << "\n";
    
    			    if (onair == 1)
    			    {
    				send(c, "Leider ist der Stream bereits besetzt.", 38, 0);
    				cout << "Sorry Message sendet\n";
    			    }
    
    			    if (onair == 0)
    			    {
    				onair = 1;
    				//system("killall -KILL sc_trans ");
    				cout << "Killed sc_trans\n\n";
    				Casting(c);
    				onair = 0;
    			    }
    			}
    		    }
    		    close(c);
    	    }
    	}
        }
    
        close(s);
    }
    


  • das kommt daher weil du den socket in den non-blocking modus gesetzt hast.



  • das ist ja soweit ich das verstanden hab das ziel, so das man weiterarbeiten kann...



  • so wie du das programmiert hast ist das aber sinnfrei! du musst noch select, poll, epoll oder etwas ähnliches einbauen.



  • Richtig. Non-Blocking heisst ja eben dass recv nicht wartet bis ein komplettes Paket angekommen ist. Folglich signalisiert er Dir "es sind gerade keine Daten zu empfangen". Mit select/poll/epoll kannst Du dann mehrere Sockets gleichzeitig darauf testen ob Daten zu empfangen sind und bei denen das der Fall ist diese verarbeiten...


Anmelden zum Antworten