Shoutcast senden
-
Guten Tag Community
Ich bin Stream-Leiter eines Internetradios. Wir benutzen sc_trans (für welche das etwas sagt) um damit den Stream mit musik zu füllen, wenn kein Moderator online ist. Wir möchten nun, das sobald ein Moderator auf den Server verbindet dieses sc_trans beendet wird, so das der Moderator senden kann.
Ich bin neuling in C++ und hab mich per Internet über die socket, bind, listen und connect funktionen informiert. Das ganze geht auch sehr gut, also das verbinden zum Tool. auch die Verbindung zum Shoutcast-Server funktioniert ohne probleme, nur, mein Tool sendet die Emfpangenen Bytes vom Moderator nicht an den Server, der Moderator sendet diese an den Server, jedoch der nicht an den Shoutcast-Server.
ziel ist es zudem, das sobald der Moderator wieder offline ist, der sc_trans wieder gestartet wird, und das im hintergrund, was bis jetzt auch noch nicht richtig geklappt hat.
ich hab per url unten die datei verlinkt und wäre sehr froh wenn sich fachkundige mein problem mal anschauen könnten und mir tipps/tricks/verbesserungen sagen können, welche ich an meinem tool vornehmen kann. das ganze läuft auf Linux und ist mit einem Proxy-Servre zu vergleichen.
Datei: http://www.zepi.eu/ec.zip
Ich danke für die Hilfe
MfG
ps. es ist zu beachten (wenn man es ausprobieren will), das die normalen shoutcast-server auf einem port (standart 8000 senden, und auzf 8001 empfangen. bei der verbindung zu einem server im tool muss der emfpangsport eingegeben, und nicht der sendeport, werden. zudem kontaktiert man das tool immer auf einer portnummer höher als das man beim dsp-plugin eigegeben hat. d.h. man gibt beim dsp-plugin 8000 ein, der server empfängt aber auf 8001 und auf diesen port sendet das dsp-plugin auch....
xstream
-
also ich hab mir den code erstmal nur ein bischen angeschaut aber du solltest dich entscheiden ob du C oder C++ programmierst. meines wissens (lass mich da gerne belehren) ist
#include <stdio.h>
C und
#include <iostream>
ist C++
... falls du noch was vergessen hast poste bitte nochmals alle informationen etc, habs bis jetzt nocht net richtig gecheckt wie das system funktioniert... werd den code aber nochmals überschaun.
mfg blan
-
ah also gedacht ist c++...
das script soll so funktionieren:
| Öffne Socket
| Binde Socket
| Hören auf 8002
| |- Empfangen von Eingehender Verbindung, wenn keine Verbindung besteht
| | | Killen von AutoPlaylist
| | | Connectend zum Shoutcast-Server
| | | Empfangen der Musik vom Moderator und Senden an den Shoutcast-Server
| | | Verbindung verlieren
| | | AutoPlaylist starten
| |- Empfangen von Eingehender Verbidung, wenn eine Verbindung besteht
| | | Anzeigen der Möglichen Befehlen
| | | Ausführen der Gewählten Befehlen
| Verbindung schliessenHoffe das ist eine Verständlichere Übersicht.
Nun hab ich Probleme beim Empfangen der Musik vom Moderator und Senden an der Shoutcast-Server. Ich hab da eine Schleife gemacht, welche sich beim Verlierne der verbindung beendet aber die schleife wird irgendwie nicht richtig ausgeführt und die daten von client werden von meinem tool auch nicht richtig emfpangen. das tool sollte mir das passwort zuschicken und das ist momentan einfach test bzw. gewesen aber vom passwort hab ich nur tes empfangen und nciht test. ich wäre froh, wenn mir mal jemand den quelltext anschauen kann und mir tipps tricks geben kann, wo welches problem entstehen könnte...
mfg
xstream
-
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 unavailablekann 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.