macos - 如何在Scala中读取网络流?

标签 macos scala networking audio streaming

如何使用Scala语言从互联网读取音频流(例如http://70.36.96.24:13384/;stream.mp3)并将其内容保存到本地磁盘?

我试图做到这一点:

val stream = new URL("http://70.36.96.24:13384/stream.mp3").openStream()

但这引发了这个异常:
java.io.IOException: Invalid Http response
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1342)
at java.net.URL.openStream(URL.java:1037)
at .<init>(<console>:15)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
    ...

相同的命令可与此其他流网址一起使用:例如
http://174-123-32-173.webnow.net.br/98fm.mp3
更新:此代码在Linux上可以完美运行,但在Mac上则不能。有人知道原因吗?

UPDATE2:实际上,此代码在Java 6上有效,但在Java7中不可用。操作系统无关紧要。

最佳答案

您的代码无效,因为服务器未发送有效的HTTP响应。请注意,此 HTTP请求已发送,正在等待响应... 200没有 header ,假定为HTTP / 0.9

$ wget -O- "http://70.36.96.24:13384/;stream.mp3" 
--2014-01-20 17:09:12--  http://70.36.96.24:13384/;stream.mp3
Connecting to 70.36.96.24:13384... connected.
HTTP request sent, awaiting response... 200 No headers, assuming HTTP/0.9
Length: unspecified
Saving to: `STDOUT'

    [<=>                                                                                                                 ] 0           --.-K/s              ICY 200 OK
icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.8<BR>
icy-name:Radio Brasileirissima
icy-genre:Musica Brasileira
icy-url:http://radiobrasileirissima.com.br
content-type:audio/mpeg
icy-pub:0
icy-br:64

....BINARY CONTENT SKIPPED....

您仍然可以通过跳过前几行来读取数据,直到字符序列\r\n\r\n(icy-br:64结束),并且实际的音频内容开始。为此,您可以创建一个Socket,将其连接并向GET发送请求到//stream.mp3并读取数据:
val timeout = 2000
val host = "70.36.96.24"
val port = 13384
val socket = new Socket
val endPoint = new InetSocketAddress(host, port)
socket.connect(endPoint, timeout);
// Here you send the GET request and read back the response.
// Every time you read the response, you have to skip
// the first few bytes until `\r\n\r\n`

EDIT1

注意:您的GET请求必须包含额外的换行符才能成为HTTP请求
GET /;stream.mp3 HTTP/1.1

Here is the working example on the same URL:

  def socketurl = {
    val timeout = 2000
    val host = "70.36.96.24"
    val port = 13384
    val socket = new Socket
    val endPoint = new InetSocketAddress(host, port)
    socket.connect(endPoint, timeout);
    val (in, out) = (socket.getInputStream(), socket.getOutputStream())
    val httpRequest = "GET /;stream.mp3 HTTP/1.1\r\n\r\n"
    val command = httpRequest.getBytes()
    println(httpRequest)
    out.write(command)

    var buf = Vector(0, 0, 0, 0)
    var c = in.read()
    var cont = true
    while (c != -1 && cont) {
      buf = buf.drop(1) :+ c
      print(c.toChar)
      if (buf(0) == '\r' && buf(1) == '\n' && buf(2) == '\r' && buf(3) == '\n') {
        cont = false
        println("Its a match")
      }
      c = in.read()
    }

    while (c != -1) {
      // keep buffering the data from here on!
    }
  }

// call the method 
socketurl

关于macos - 如何在Scala中读取网络流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20972651/

相关文章:

macos - 为什么在 “about”菜单中显示的应用程序名称与应用程序名称不同? ( Electron ,MacOS)?

macos - 如何在 OSX 上解压缩 omni.ja?

c++ - 使用 recvfrom 获取数据

Java Socket/Serversocket WAN 连接

macos - 如何使用 NSPageController 在 NSViewController 之间切换?

C++ 解析二进制 plist

Scala 中的 Python 风格装饰器

使用 scala 解析器组合器解析基于缩进的语言

scala - 为什么 SBT 的 Scala (2.10) 不包括 Akka?

c++ - 如何使用 select() 来监视对象?