http发送流数据问题,可能的原因和解决办法
2013-03-14 15:56
639 查看
http://hi.baidu.com/sunwater007/item/1438dc098af313803c42e290
此程序是目的是以http的方式循环的把一个流数据发送到media player.
为了调试这个socket问题,整整让我痛苦了四天.
正常情况下的socket的同步编程不是太难,我原以为这个小程序应该不会有问题,然而,我错了.
程序让我失望了,而且这种错误是不可跟踪的,而且出现是有概率的.更增加了调试难度.
试了N久,我突然在调试的时候不断的换port,发现每次第一次换port,media player都能正常的接收到所有的数据.然而,如果故意让media player故意发一个错误的http请求,那么接下来media player一般在接受到第一个Block的以后强迫关闭TCP连接.致使server出错.
我猜想可能media player是有缓冲的,如果第一次接受到数据,cache进去,下次再请求,它发现还是相同的block,可能就主动关闭tcp.因为在使用http封装的block里就没有指出content-length,这个普通的http是有些不一样.
而且media player在首次请求的时候会首先发自己的一个参数信息列表,但是不需要接受数据.所以需要给它一个204的响应代码.
所以为了避免这些问题,我在发送完成后就关闭掉BinaryReader,FileStream和passive socket,目前出现不能接受数据的概率大大减少.其实在实际应用当中是不应该关闭socket的.也不存在多次http请求的问题.
程序如下:
==============
protected void start_listen()
{
const int BLOCK_SIZE = 64 * 1024;
const string LOCAL_IP = "127.0.0.1";
const int IP_PORT = 21100;
int received_http_head_length = -1;
Socket server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint local_endpoint = new IPEndPoint(IPAddress.Parse(LOCAL_IP), IP_PORT);
server_socket.Bind(local_endpoint);
try
{
do
{
server_socket.Listen(10);
Socket passive_socket = server_socket.Accept();
Byte[] http_request_head = new byte[512 * 1024];
received_http_head_length = passive_socket.Receive(http_request_head);
if(received_http_head_length < 0)
{
break;
}
else
{
string request_http_head_string = Encoding.Default.GetString(http_request_head, 0, received_http_head_length);
string response_http_head_string = null;
if(request_http_head_string.IndexOf("Connection: Keep-Alive") != -1)
{
FileStream video_file_stream = new FileStream(@"e:\test.wmv", FileMode.Open, FileAccess.Read);
Byte[] video_file_stream_buffer = new byte[video_file_stream.Length];
BinaryReader bin_reader = new BinaryReader(video_file_stream);
bin_reader.Read(video_file_stream_buffer, 0, video_file_stream_buffer.Length);
response_http_head_string += "HTTP/1.1 200 OK\r\n";
response_http_head_string += "Content-Type: video/octet-stream\r\n";
response_http_head_string += "\r\n";
Byte[] response_http_head_buffer = Encoding.ASCII.GetBytes(response_http_head_string);
passive_socket.Send(response_http_head_buffer, 0, response_http_head_buffer.Length, SocketFlags.None);
for(int i = 0; i <= video_file_stream.Length / BLOCK_SIZE; i++)
{
if( i != video_file_stream.Length / BLOCK_SIZE)
{
passive_socket.Send(video_file_stream_buffer, i * BLOCK_SIZE, BLOCK_SIZE, SocketFlags.None);
}
else
{
passive_socket.Send(video_file_stream_buffer, i * BLOCK_SIZE, video_file_stream_buffer.Length - i * BLOCK_SIZE, SocketFlags.None);
}
}
passive_socket.Close();
bin_reader.Close();
video_file_stream.Close();
}
else
{
response_http_head_string += "HTTP/1.1 204 OK\r\n";
response_http_head_string += "\r\n";
Byte[] response_http_head_buffer = Encoding.ASCII.GetBytes(response_http_head_string);
passive_socket.Send(response_http_head_buffer, 0, response_http_head_buffer.Length, SocketFlags.None);
passive_socket.Close();
}
}
}while(true);
}
catch(Exception ex)
{
Console.Write(ex.Message);
}
}
private void listen_btn_Click(object sender, System.EventArgs e)
{
listen_btn.Enabled = false;
start_listen();
}
此程序是目的是以http的方式循环的把一个流数据发送到media player.
为了调试这个socket问题,整整让我痛苦了四天.
正常情况下的socket的同步编程不是太难,我原以为这个小程序应该不会有问题,然而,我错了.
程序让我失望了,而且这种错误是不可跟踪的,而且出现是有概率的.更增加了调试难度.
试了N久,我突然在调试的时候不断的换port,发现每次第一次换port,media player都能正常的接收到所有的数据.然而,如果故意让media player故意发一个错误的http请求,那么接下来media player一般在接受到第一个Block的以后强迫关闭TCP连接.致使server出错.
我猜想可能media player是有缓冲的,如果第一次接受到数据,cache进去,下次再请求,它发现还是相同的block,可能就主动关闭tcp.因为在使用http封装的block里就没有指出content-length,这个普通的http是有些不一样.
而且media player在首次请求的时候会首先发自己的一个参数信息列表,但是不需要接受数据.所以需要给它一个204的响应代码.
所以为了避免这些问题,我在发送完成后就关闭掉BinaryReader,FileStream和passive socket,目前出现不能接受数据的概率大大减少.其实在实际应用当中是不应该关闭socket的.也不存在多次http请求的问题.
程序如下:
==============
protected void start_listen()
{
const int BLOCK_SIZE = 64 * 1024;
const string LOCAL_IP = "127.0.0.1";
const int IP_PORT = 21100;
int received_http_head_length = -1;
Socket server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint local_endpoint = new IPEndPoint(IPAddress.Parse(LOCAL_IP), IP_PORT);
server_socket.Bind(local_endpoint);
try
{
do
{
server_socket.Listen(10);
Socket passive_socket = server_socket.Accept();
Byte[] http_request_head = new byte[512 * 1024];
received_http_head_length = passive_socket.Receive(http_request_head);
if(received_http_head_length < 0)
{
break;
}
else
{
string request_http_head_string = Encoding.Default.GetString(http_request_head, 0, received_http_head_length);
string response_http_head_string = null;
if(request_http_head_string.IndexOf("Connection: Keep-Alive") != -1)
{
FileStream video_file_stream = new FileStream(@"e:\test.wmv", FileMode.Open, FileAccess.Read);
Byte[] video_file_stream_buffer = new byte[video_file_stream.Length];
BinaryReader bin_reader = new BinaryReader(video_file_stream);
bin_reader.Read(video_file_stream_buffer, 0, video_file_stream_buffer.Length);
response_http_head_string += "HTTP/1.1 200 OK\r\n";
response_http_head_string += "Content-Type: video/octet-stream\r\n";
response_http_head_string += "\r\n";
Byte[] response_http_head_buffer = Encoding.ASCII.GetBytes(response_http_head_string);
passive_socket.Send(response_http_head_buffer, 0, response_http_head_buffer.Length, SocketFlags.None);
for(int i = 0; i <= video_file_stream.Length / BLOCK_SIZE; i++)
{
if( i != video_file_stream.Length / BLOCK_SIZE)
{
passive_socket.Send(video_file_stream_buffer, i * BLOCK_SIZE, BLOCK_SIZE, SocketFlags.None);
}
else
{
passive_socket.Send(video_file_stream_buffer, i * BLOCK_SIZE, video_file_stream_buffer.Length - i * BLOCK_SIZE, SocketFlags.None);
}
}
passive_socket.Close();
bin_reader.Close();
video_file_stream.Close();
}
else
{
response_http_head_string += "HTTP/1.1 204 OK\r\n";
response_http_head_string += "\r\n";
Byte[] response_http_head_buffer = Encoding.ASCII.GetBytes(response_http_head_string);
passive_socket.Send(response_http_head_buffer, 0, response_http_head_buffer.Length, SocketFlags.None);
passive_socket.Close();
}
}
}while(true);
}
catch(Exception ex)
{
Console.Write(ex.Message);
}
}
private void listen_btn_Click(object sender, System.EventArgs e)
{
listen_btn.Enabled = false;
start_listen();
}
相关文章推荐
- 后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法
- 后端接收不到AngularJs中$http.post发送的数据原因分析及解决办法
- Python中使用socket发送HTTP请求数据接收不完整问题解决方法
- oracle排序,出现页数不同数据却重复问题的原因及解决办法
- ArcGIS 10.1 for Server 数据注册失败的一种可能原因及解决办法
- MFC串口发送数据大于128数据出错的解决办法(发送0xFE接收得到0x3F等问题)
- Python中使用socket发送HTTP请求数据接收不完整问题解决方法
- WordPress ”无法发送电子邮件,可能原因:您的主机禁用了mail()函数“的解决办法
- 在很多论坛上看到了有人抱怨Flash CS5中,代码提示(Code hint)有时不显示的问题,这个问题可能有很多原因,我整理了几个解决办法,有可能可以帮助到你~
- 连续点击按钮后多次发送数据问题的解决办法
- 解决MVC3 服务器无法在已发送 HTTP 标头之后设置状态 问题
- PDO取Oracle lob大字段,当数据量太大无法取出的问题的解决办法
- HttpURLConnection上传大文件内存溢出的原因及解决办法
- scst target在设置开机自启动时所遇问题的原因及解决办法
- android编程中遇到的关于调试百度地图时出现的 java.lang.UnsatisfiedLinkError: initClass 问题的原因及解决办法
- 安装使用Android Studio时可能出现的几个问题解决办法
- Oracle存储过程造数据,遇到问题解决办法
- 白苹果问题解决办法以及原因简单分析
- jQuery在异步请求数据返回后,调用$("selector").html(data.content);之后因为一些特殊字符或者',"不能显示内容的问题解决办法
- JDBC链接mysql插入数据后显示问号的原因及解决办法