http发送流数据问题,可能的原因和解决办法

来源:互联网 发布:阿里云备案服务号购买 编辑:程序博客网 时间:2024/05/15 06:07

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();
}