我目前正在研究一个小型项目,该项目通过http.ServeContent将视频提供给浏览器或其他媒体客户端。我已经实现了自己的ReadSeeker,它看起来像这样:
//the seek is not fully working yet but works fine for the initial two calls that is being called internally from http to decide the file size.
func (c *Client) Seek(offset int64, whence int) (t int64, e error) {
switch whence {
case 0:
t = offset
case 1:
t = c.seek + offset
case 2:
t = c.SelectedFile().Length + offset
}
if c.seek != t {
//TODO
c.seek = t
}
return
}
func (c *Client) Read(p []byte) (n int, err error) {
if c.done {
return 0, io.EOF
}
for {
result := <-c.Results
if result.piece == nil {
return 0, io.EOF
}
for i, b := range result.bytes {
index := int64(i)
if index < 0 || index > c.SelectedFile().Length {
continue
}
n++
p[index] = b
}
return
}
}
例如,如果我使用curl来获取数据,则一切正常且繁琐,例如,数据一直在流传输(每次读取1024字节)。但是,一旦我使用浏览器甚至是VLC,在5到10之间读取http writer.Write()就会返回EPIPE错误并且连接断开。错误似乎直接来自io.go内部的dst.Write(buf [0:nr]):
...
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
...
for {
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = ErrShortWrite
break
}
}
if er != nil {
if er != EOF {
err = er
}
break
}
}
return written, err
}
我已经尝试调试了好几天,似乎无法找出原因。我一直在比较我提供的字节与实际文件,似乎数据没有任何问题。
任何想法可能有什么问题吗?
答案 0 :(得分:1)
没有错。没有什么要求客户端在服务器发送完所有数据之前不断开连接。客户端执行标准的http请求,然后在收到标头后取消,这非常常见,尤其是对于mp4文件。
我怀疑视频没有按照您期望的方式播放?如果是这种情况,请确保您的服务器实现了http范围请求。