URLConnection unter 1.7 macht Probleme

windl

Bekanntes Mitglied
Hi NG,

wenn ich versuche einen Shoutcast-Stream mit URLConnection zu öffnen bekomme ich unter JAVA 1.7 die Fehlermeldung "Invalid Stream Header". Dieses Verhalten tritt unter Java 1.6 nicht auf - da klappt alles wunderbar ???:L
Google hat mir mitgeteilt, dass in dieser Version der Header untersucht wird. Dieser muss unbedingt mit "HTTP" beginnen. Da ich aber einen Shoutcast-Stream einlade, beginnt dieser nicht mit diesem Flag sondern ich empfange einen Stream welchen ich direkt in einen Player übergeben kann.

Als Work-Around wurde mir mitgeteilt, wenn dieser Fehler auftritt den ErrorStream auszulesen. Dieser ist aber NULL.

Kennt einer von Euch eine Möglichkeit den InputStream zu empfangen?

Danke
Uwe
 
Zuletzt bearbeitet:

windl

Bekanntes Mitglied
Hallo,

also hier ein paar Zeilen Code. Bitte - die angegebene URL ist eine Shoutcast-Url und kann sich ändern!
Ich betone noch einmal unter Java 1.6 läuft es. Allerdings gibt es in Java 1.7 einige wunderbare Erweiterungen zu 1.6 auf die ich nicht mehr verzichten möchte.

Java:
URL tUrl = new URL("http://scfire-mtc-aa06.stream.aol.com:80/stream/1060");
URLConnection  con = (URLConnection)tUrl.openConnection();
con.setReadTimeout(1000);
InputStream stream = con.getInputStream();

Darauf bekomme ich die folgende Fehlermeldung:
Java:
java.io.IOException: Invalid Http response
at sun.net.[url]www.protocol.http.HttpURLConnection.getInputStream(Unknown[/url] Source)

Danke
Uwe
 

mfernau

Bekanntes Mitglied
Eine kurze Info darüber wie Du das Problem gelöst hast würde einem Suchenden die erneute Frage zu diesem Thema ersparen ;-)
 

windl

Bekanntes Mitglied
Folgende Lösung habe ich für mein Problem gefunden.
Bitte - das ist nur eine "Quick and dirty" Implementierung.
Aus diesem Ansatz heraus werde ich noch eine saubere Klasse entwickeln, die mit Proxy und TimeOut umgehen kann.

Java:
try{
			URL url = new URI("http://scfire-mtc-aa06.stream.aol.com:80/stream/1060").toURL();
			System.out.println(url.getPath());
		
			Socket socket = new Socket(url.getHost(),url.getPort());
			
			PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))); 
			out.println("GET "+url.getPath()+" HTTP/1.0"); 
			out.println(); 
			out.flush(); 

			BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

			String inputLine; 
			int count = 0; 

			while ((inputLine = in.readLine()) != null) { 
			count++; 
			System.out.println(count); 
			System.out.println(inputLine); 
			} 

			in.close(); 
}catch(Exception error){
	error.printStackTrace();
}

Jetzt bekommme ich wieder sauber den Shoutcast-Stream welchen ich meinem Player übergeben kann.
 
N

nillehammer

Gast
Ich habe diesen Thread gestern bereits verfolgt, aber nichts geschrieben, weil ich nichts Sinnvolles beitragen konnte. Danke für das Posten Deiner Lösung. Hat mich auch interessiert. Soo Q&D finde ich die garnicht. Eine kleiner Tipp nur:
Java:
URL url = new URI("http://scfire-mtc-aa06.stream.aol.com:80/stream/1060").toURL();
Du brauchst nicht in URL zu konvertieren. Die ganzen Methoden, die Du später benutzt (getPort etc.) gibt es auch direkt in URI.
 

HoaX

Top Contributor
Wenn man sich den Response vom Server anschaut, dann ist es durchaus berechtigt dass URL meckert. Das ist nichtmal HTTP/1.0 sondern irgendwas davor.
 

windl

Bekanntes Mitglied
Ja, es ist ein Shoutcast-Stream mit einem ICY-Header.

ICY 200 OK
icy-notice1: <BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
icy-notice2: Firehose Ultravox/SHOUTcast Relay Server/Linux v2.6.0<BR>
icy-name: #MUSIK.GOLDIES - #Musik Internetradio, Webradio, Online Radio - RauteMusik.FM - 24H OLDIES CLASSIC ROCK 60S 70S 80S POP AND MORE!
icy-genre: Decades Oldies 80s 70s 60s
icy-url: #Musik Internetradio, Webradio, Online Radio - RauteMusik.FM
content-type: audio/mpeg
icy-pub: 1
icy-br: 128
 

windl

Bekanntes Mitglied
Auch wenn es nicht mit einem HTTP anfängt - es ist und bleibt eine URL-Adresse.
Es sollte trotzdem möglich sein, einen solchen Stream mit Java-Boardmitteln zu laden.
Ich will keine rhetorische Frage aufwerfen aber der Stream ist via URL zu erreichen aber in JAVA 1.7 nicht mehr mit Java-Boardmitteln zu erreichen!
Ist diese zusätzliche Implementierung nicht etwas kurz gedacht und der Blick über den Tellerrand wurde nicht getan?

Ich bedanke mich für die tollen Anregungen!
Super Forum
Uwe
 

HoaX

Top Contributor
Auch wenn es nicht mit einem HTTP anfängt - es ist und bleibt eine URL-Adresse.
Es sollte trotzdem möglich sein, einen solchen Stream mit Java-Boardmitteln zu laden.
Ich will keine rhetorische Frage aufwerfen aber der Stream ist via URL zu erreichen aber in JAVA 1.7 nicht mehr mit Java-Boardmitteln zu erreichen!
Ist diese zusätzliche Implementierung nicht etwas kurz gedacht und der Blick über den Tellerrand wurde nicht getan?

Ich bedanke mich für die tollen Anregungen!
Super Forum
Uwe

Ich denke du hast eine falsche Definition von URL. Auch mailto://adler@horst.invalid?subject=Schwul ist eine gültige URL. Dennoch wird URL#openConnection() nicht funktionieren, da es auch keinen Sinn macht.
Bei deiner URL steht vorne, als Protokoll, http://. Entsprechend wird auch eine HTTP-Antwort erwartet und nicht Shoutcast.

URL (Java Platform SE 6) sagt auch welche Protokolle unterstützt werden. Wenn Shoutcast trotzdem geht dann ist das halt Zufall/Toleranz, dennoch darf man sich eben nicht darauf verlassen. Auch sagt dir der Link wir du deinen eingenen Protokollhandler registrieren kannst, so dass du z.B. shoutcast://... als URL verwenden kannst.
 
Zuletzt bearbeitet:

Empire Phoenix

Top Contributor
Warum nicht einfach nen TCP connection manuall aufbauen und von dort lesen?
Benötigten request (von wgen url) noch vorher manuell rausschieben.

-> Keine abhängigkeit von bug verhalten der jvm
-> sauber
-> zukunftsicher
 

windl

Bekanntes Mitglied
Hi NG,

Ihr habt absolut Recht, Java verhält sich richtig. In Unwissenheit zu schnell geschrieben ;o(

Trotzdem - das Problem dass man den Stream nicht mehr bekommt blieb erhalten.
Habe jetzt eine Klasse erstellt, die für meine Belange absolut reicht. Was ich zusätzlich eingebaut habe ist ein HTTP-Proxy für eine Socketinstanz.

Muss gestehen, ich bin kein Netzwerkspezialist in Java somit mögen sich mit Sicherheit einige Fehler im Source tummeln.

Es wäre schön, wenn ich darauf konstruktive Kritik erhalten würde - bzw wenn sich der Eine oder Andere finden würde der den Source evtl weiter ausbauen möchte.

Java:
package mediaGate.generalFrontend.streamConnection;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;

public class MediaGateURLConnection {

	//hält die URL, mit der man sich verbinden möchte
	private URI localURL = null;
	//hält die Socketverbindung
	private Socket socket	= null;
	//ConnectionTimout
	private int defaultConnectTimeout = -1;
	
	private HTTPSocketTunnel sTunnel = null;
	
	/**Übergeben einer URL*/
	public MediaGateURLConnection(String url){
		this(url,"",-1);
	}
	
	/**Übergeben einer URL und eines Proxy*/
	public MediaGateURLConnection(String url,String host, int port){
		this(url,host,port,0);
	}
	
	/**Übergeben einer URL und eines Proxy und einer connection-timeout
	 * Der Proxy kann auch "" und der Port -1 sein, wenn man eine timeout mitgeben will */
	public MediaGateURLConnection(String url,String host,int port,int timeout){
		try{
		
			//ConnectionProperties einlesen
			//Die Java-Defaulteinstellungen werden ausgelesen
			readConnectionProperties();
			
			if(port>-1){
				//Implementierung mit PROXY
				sTunnel = new HTTPSocketTunnel(host,port,timeout);
				sTunnel.connectURL(url);
				
			} else {
				//Implementierung ohne PROXY
				//Ab hier wird die Verbindung selber erstellt.
				localURL = new URI(url);
				
				//Socket erstellen
				socket = createSocket(localURL.getHost(), localURL.getPort(), timeout);
		       
				//Sollte ein Unterpfad in der URL vorhanden sein, dann in
				//diesen Pfad wechseln.
				if(!localURL.getPath().equals("")){
					//Unteren Pfad abfragen
					changeServerPath(new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))),localURL.getPath());
				}
			}
		}catch(Exception error){
			error.printStackTrace();
		}
	}

	
	/** gibt den InputStream als BufferedInputStream der Socket zurück oder NULL bei einem Fehler
	 *  BufferedInputstream deswegen, da für den Shoutcast-Stream ein Stream benötigt wird, der das Flag 
	 *  markSupported auf TRUE hat. */
	public BufferedInputStream getInputStream(){
		try{
			
			if(sTunnel != null){
				return new BufferedInputStream(sTunnel.getInputStream());
			}
			if(socket != null){
				return new BufferedInputStream(socket.getInputStream());
			}
		}catch(Exception error){}
		return null;
	}
	
	/**Beendet die vorhandene Verbindung*/
	public void closeConnection(){
		try{
			if(sTunnel != null){
				sTunnel.closeServer();
			} else {
				socket.close();
			}
		}catch(Exception error){
			error.printStackTrace();
		}
	}
	
	/**Die benötigten Javastandards auslesen*/
	private void readConnectionProperties(){
		
		int vals[] = {0, 0};
		String encs[] = { null };
		
		vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue();
		vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue();
		encs[0] = System.getProperty("file.encoding", "ISO8859_1");
		
		defaultConnectTimeout = vals[1] == 0?-1:vals[1];
	
	}
	
	
	private class HTTPSocketTunnel {

		//hält die Serversocket
		private Socket sSocket = null;
		//hält den outputStream um darüber die URL via HTTP-Proxy anzufordern
		private PrintWriter outputStream = null;
		
		
		private HTTPSocketTunnel(String host,int port,int timeout){
			try{
				sSocket = createSocket(host,port,timeout);
				sSocket.setSoTimeout(0);
				outputStream = new PrintWriter(new BufferedWriter(new OutputStreamWriter(sSocket.getOutputStream()))); 
				
			}catch(Exception error){}
		}
		
		/**Diese Funktion wechselt im Server zur entsprechenden URL*/
		private void connectURL(String url){
			changeServerPath(outputStream,url);
		}

		/**gibt den InputStream zur URL zurück*/
		private InputStream getInputStream(){
			try{
				return sSocket.getInputStream();
			}catch(Exception error){}
			
			return null;
		}
		
		/**Der Server wird geschlossen*/
		private void closeServer(){
			try{
				sSocket.close();
				outputStream = null;
			}catch(Exception error){}
		}
		
	}
	
	
	//#####################################################################################
	//## Hilfefunktion wie Socket erstellen unter Berücksichtigung der Timeout
	//##
	//## Serverpfad wechseln
	//#####################################################################################
	private Socket createSocket(String url,int port, int timeout){
		try{
			Socket socket = new Socket();
			if (timeout >= 0) {
	            socket.connect(new InetSocketAddress(url, port), timeout);
	        } else {
	            if (defaultConnectTimeout > 0) {
	                socket.connect(new InetSocketAddress(url, port), defaultConnectTimeout);
	            } else {
	                socket.connect(new InetSocketAddress(url, port));
	            }
	        }
			return socket;
		}catch(Exception error){
			error.printStackTrace();
		}
		return null;
	}
	
	private void changeServerPath(PrintWriter out,String urlPath){
		out.println("GET "+urlPath+" HTTP/1.0"); 
		out.println(); 
		out.flush(); 
	}
	//#####################################################################################
	//## Ende der Hilfefunktionen
	//#####################################################################################
}
 

windl

Bekanntes Mitglied
Hi NG,

nun muss ich doch noch ein UPDATE nachschieben. Verbunden mit einer Frage!

Ich hatte folgendes Problem, dass wenn ich den INPUTSTREAM an JLAYER (javazoom) übergeben habe, habe ich die Lied-Informationen nicht erhalten. Etwas musste ich im Package mp3spi1.9.5 umbauen dass es klappt und ich musste meine Klasse ertüchtigen dass sie mit setRequestProperty() umgehen kann.
Beides habe ich nun geschafft und ich bekomme die Titelinformationen wieder angezeigt.

Nun zu meiner Frage. Wie kann ich denn in diese Klasse die Funktion getHeaderField(String ) implementieren?

Java:
package mediaGate.generalFrontend.streamConnection;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;
import java.util.ArrayList;

public class MediaGateURLConnection {

	//hält die URL, mit der man sich verbinden möchte
	private URI localURL = null;
	//hält die Socketverbindung
	private Socket socket	= null;
	//ConnectionTimout
	private int defaultConnectTimeout = -1;
	/**hält eine Insanz zum HTTP-ProxyTunnel*/
	private HTTPSocketTunnel sTunnel = null;
	/**hält den PrintWriter*/
	private PrintWriter outWriter = null;
	/**Eine Liste für UserProperties die beim GET mitgegeben werden können*/
	private ArrayList<String> propertyList = null;
	
	private String url 		= "";
	private String host		= "";
	private int port		= -1;
	private	int timeout		= -1;
	
	
	
	/**Übergeben einer URL*/
	public MediaGateURLConnection(String url){
		this(url,"",-1);
	}
	
	/**Übergeben einer URL und eines Proxy*/
	public MediaGateURLConnection(String url,String host, int port){
		this(url,host,port,0);
	}
	
	/**Übergeben einer URL und eines Proxy und einer connection-timeout
	 * Der Proxy kann auch "" und der Port -1 sein, wenn man eine timeout mitgeben will */
	public MediaGateURLConnection(String url,String host,int port,int timeout){
		this.url 		= url;
		this.host 		= host;
		this.port 		= port;
		this.timeout 	= timeout;
	}

	
	/** gibt den InputStream als BufferedInputStream der Socket zurück oder NULL bei einem Fehler
	 *  BufferedInputstream deswegen, da für den Shoutcast-Stream ein Stream benötigt wird, der das Flag 
	 *  markSupported auf TRUE hat. */
	public InputStream getInputStream(){
		try{
			
			try{
				
				//ConnectionProperties einlesen
				//Die Java-Defaulteinstellungen werden ausgelesen
				readConnectionProperties();
				
				if(port>-1){
					//Implementierung mit PROXY
					sTunnel = new HTTPSocketTunnel(host,port,timeout);
					sTunnel.connectURL(url);
					
				} else {
					//Implementierung ohne PROXY
					//Ab hier wird die Verbindung selber erstellt.
					localURL = new URI(url);
					
					//Socket erstellen
					socket = createSocket(localURL.getHost(), localURL.getPort(), timeout);
			       
					//Sollte ein Unterpfad in der URL vorhanden sein, dann in
					//diesen Pfad wechseln.
					if(!localURL.getPath().equals("")){
						//Unteren Pfad abfragen
						outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
						changeServerPath(localURL.getPath());
					} else {
						//Der Pfad ist leer aber trotzdem kann etwas in den Requestproperties stehen die noch gesendet werden müssen
						if(propertyList!=null){
							changeServerPath(localURL.getHost());
						}
					}
				}
			}catch(Exception error){
				error.printStackTrace();
			}
			
			
			if(sTunnel != null){
				return new BufferedInputStream(sTunnel.getInputStream());
			}
			if(socket != null){
				return new BufferedInputStream(socket.getInputStream());
			}
		}catch(Exception error){}
		return null;
	}
	
	/**Beendet die vorhandene Verbindung*/
	public void closeConnection(){
		try{
			if(sTunnel != null){
				sTunnel.closeServer();
			} else {
				socket.close();
			}
		}catch(Exception error){
			error.printStackTrace();
		}
	}
	
	/**Die benötigten Javastandards auslesen*/
	private void readConnectionProperties(){
		
		int vals[] = {0, 0};
		String encs[] = { null };
		
		vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue();
		vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue();
		encs[0] = System.getProperty("file.encoding", "ISO8859_1");
		
		defaultConnectTimeout = vals[1] == 0?-1:vals[1];
	
	}
	
	
	private class HTTPSocketTunnel {

		//hält die Serversocket
		private Socket sSocket = null;
		
		private HTTPSocketTunnel(String host,int port,int timeout){
			try{
				sSocket = createSocket(host,port,timeout);
				sSocket.setSoTimeout(0);
				outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(sSocket.getOutputStream()))); 
				
			}catch(Exception error){}
		}
		
		/**Diese Funktion wechselt im Server zur entsprechenden URL*/
		private void connectURL(String url){
			changeServerPath(url);
		}

		/**gibt den InputStream zur URL zurück*/
		private InputStream getInputStream(){
			try{
				return sSocket.getInputStream();
			}catch(Exception error){}
			
			return null;
		}
		
		/**Der Server wird geschlossen*/
		private void closeServer(){
			try{
				sSocket.close();
				outWriter.close();
				outWriter = null;
			}catch(Exception error){}
		}
		
	}
	
	/** Es können nun beim GET auch noch USER-Informationen mitgegeben werden!
	 *  Beispiel hierfür ist setRequestProperty("Icy-Metadata", "1"); für den ShoutcastStream 
	 **/
	public void setRequestProperty(String property,String value){
		if(propertyList == null){
			propertyList = new ArrayList<String>();
		}
		propertyList.add(property+": "+value);
	}
	
	//#####################################################################################
	//## Hilfefunktion wie Socket erstellen unter Berücksichtigung der Timeout
	//##
	//## Serverpfad wechseln
	//#####################################################################################
	private Socket createSocket(String url,int port, int timeout){
		try{
			Socket socket = new Socket();
			if (timeout >= 0) {
	            socket.connect(new InetSocketAddress(url, port), timeout);
	        } else {
	            if (defaultConnectTimeout > 0) {
	                socket.connect(new InetSocketAddress(url, port), defaultConnectTimeout);
	            } else {
	                socket.connect(new InetSocketAddress(url, port));
	            }
	        }
			return socket;
		}catch(Exception error){
			error.printStackTrace();
		}
		return null;
	}
	
	private void changeServerPath(String urlPath){
		outWriter.println("GET "+urlPath+" HTTP/1.0"); 
		//Überprüfen ob etwas in den Properties steht
		//und baut diese Informationen noch mit ein
		if(propertyList != null){
			for(String line:propertyList){
				outWriter.println(line);
			}
		}
		outWriter.println(); 
		outWriter.flush(); 
	}
	
	//#####################################################################################
	//## Ende der Hilfefunktionen
	//#####################################################################################
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M HTTP URLConnection + BufferedReader killt meine Umlaute Netzwerkprogrammierung 4
U URLConnection mit lg/pw Netzwerkprogrammierung 2
C Java NIO Urlconnection Filetransfer Netzwerkprogrammierung 14
nrg HTTP URLConnection immer neu öffnen? Netzwerkprogrammierung 6
B HTTP JSESSIONID in Http(s)URLConnection loswerden! Netzwerkprogrammierung 13
R HTTP Problem bei Authentifizierung über (Http)UrlConnection Netzwerkprogrammierung 2
H URLConnection - Browseranfrage nachbauen Netzwerkprogrammierung 2
E Parameter einer URLConnection Netzwerkprogrammierung 12
A [URLConnection] Bilder hochladen - aber anders! Netzwerkprogrammierung 4
J URLConnection schließen ? Netzwerkprogrammierung 6
D FTP Über URLConnection Netzwerkprogrammierung 7
R URLConnection via Proxy mit Authentification Netzwerkprogrammierung 5
S URLConnection über Proxy Netzwerkprogrammierung 4
D URLConnection + getLastModified Netzwerkprogrammierung 13
M erst POST dann Http-Request über URLConnection Netzwerkprogrammierung 3
meez Sockettimeout bei URLConnection Netzwerkprogrammierung 2
H Mail über URLConnection Netzwerkprogrammierung 8
M JAX-WS unter Java 17 plötzlich nicht mehr möglich Netzwerkprogrammierung 5
G Programm unter anderer IP ausführen Netzwerkprogrammierung 6
Thallius HTTP HTTPS unter Java 1.6 schlägt fehl Netzwerkprogrammierung 4
B HTTP Webseite unter IP-Addresse nicht aufrufbar - unter Domain schon Netzwerkprogrammierung 9
B Socket Verbindungsverlust unter Linux erkennen Netzwerkprogrammierung 5
S soap kann nicht zu 127.0.0.1:8090 unter Windows verbinden Netzwerkprogrammierung 2
Dit_ FTP chmod | LIST unter Win und Unix Netzwerkprogrammierung 2
aze JPCap unter Windows 7(64 Bit) Netzwerkprogrammierung 6
S Problem mit 2 Serversockets unter Win XP Netzwerkprogrammierung 7
C RMI Klasse wird unter falschem Pfad gesucht Netzwerkprogrammierung 4
A Ping unter Java Netzwerkprogrammierung 5
K Wireless Programmierung unter Java? Netzwerkprogrammierung 3
G Fehlermeldung beim Erzeugen der WSDL Datei unter Axis Netzwerkprogrammierung 2
B Internetverbindung prüfen unter Windows Netzwerkprogrammierung 1
H freigabe - unterschiedliche pfade unter linux und windows Netzwerkprogrammierung 7
B Datei speichern unter Netzwerkprogrammierung 10
psysp Paket unter Linux broadcaste Netzwerkprogrammierung 2
A protokoll unter soap Netzwerkprogrammierung 3
R PID's auf remote PC unter Windows herrausfinden Netzwerkprogrammierung 2
A Socket unter Linux Netzwerkprogrammierung 4
A Was macht WebEndPoint ? Netzwerkprogrammierung 2
M Was macht Thread, wenn er aus einem "leeren" Inputstream liest ? Netzwerkprogrammierung 5
reibi Proxy macht Problem abeim URL-Aufruf Netzwerkprogrammierung 3
D EA-Exception Network Adapter macht probleme Netzwerkprogrammierung 2
K RMI macht Anwendung langsam? Netzwerkprogrammierung 8
N Java-Chat (lauffähig) macht Probleme auf der Konsole Netzwerkprogrammierung 6

Ähnliche Java Themen

Neue Themen


Oben