zoukankan      html  css  js  c++  java
  • WebIM(4)----Comet的特殊之处

    WebIM系列文章

    一步一步打造WebIM(1)一文中已经使用Comet实现了一个简单的WebIM,那么,Comet究竟和一般的打开网页有何区别,本文将通过编写一个简单的HTTP服务器来说明两者的区别。

    所谓网站,其实可以理解为服务器上的一个应用程序,该应用程序创建了一个Socket并在80端口(一般是80端口)上监听,并接受和处理浏览器发送过来的HTTP请求。

    当你打开网页时,浏览器会发送一个HTTP请求到服务器,之后浏览器将一直等待知道服务器发送完HTTP回应。当服务器接受到这个http请求后,就会解析HTTP请求的头部,根据报文中的信息向浏览器发送数据(网页,图片,数据等),当服务器发送完数据后,浏览器就结束等待,显示出网页。关于浏览器和服务器之前的交互,可以阅读这篇博文:

    HTTP协议及其POST与GET操作差异 & C#中如何使用POST、GET等

    根据以上叙述的交互过程,可以编写一个简单的http服务器,该服务器在8000端口监听,并且只提供两个网页

    http://localhost:8000/index.htm

    http://localhost:8000/comet.htm

    这两个网页的区别在于,index.htm服务器在接收到HTTP请求后立刻发送网页并结束本次链接,而Comet.htm则不是如此,是将链接先挂起,并启动一个线程,新的线程将延迟5秒再发送网页。服务器源代码如下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
    namespace http
    {
        class Program
        {
            static String ResponeFormat =
            "HTTP/1.1 200 OK
    " +
            "Content-Length: {0}
    " +
            "Connection: close
    " +
            "Content-Type: text/html
    " +
            "
    " +
            "{1}
    ";
    
            static void Main(string[] args)
            {
                Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                //在8000端口监听
                EndPoint ep = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 8000);
                server.Bind(ep);
                server.Listen(5);
    
                while (true)
                {
                    Socket client = server.Accept();
    
                    //读取HTTP报文头部
                    String header = String.Empty;
                    while (header.IndexOf("
    
    ") < 0)
                    {
                        byte[] buffer = new byte[1024];
                        int len = client.Receive(buffer);
                        header += Encoding.ASCII.GetString(buffer, 0, len);
                    }
    
                    Console.WriteLine("================================================================================");
                    Console.Write(header);
    
                    Regex reg = new Regex(@"GETs+([^s
    ]+)s+HTTP/1.1s*
    ", RegexOptions.IgnoreCase);
                    Match match = reg.Match(header);
                    if (match.Success)
                    {
                        String fname = Path.GetFileName(match.Groups[1].Value).ToLower();
    
                        if (fname == "index.htm")
                        {
                            String html = String.Format("<span style='color:red; fonst-size:24px;'>{0}</span>", DateTime.Now);
                            String response = String.Format(ResponeFormat, html.Length, html);
    
                            //发送HTTP回应,本次HTTP请求结束,浏览器将立刻接受到网页
                            client.Send(Encoding.UTF8.GetBytes(response));
                            client.Close();
                        }
                        else if (fname == "comet.htm")
                        {
                            //假设此时数据未准备好,先挂起链接,网页将在另一个线程中发送到浏览器
                            //在线程没有发送HTTP回应前,浏览器将一直等待,直到启动的线程发送回应
                            Thread thread = new Thread(new ParameterizedThreadStart(SendThreadEntry));
                            thread.Start(client);
    
                        }
                        else
                        {
                            client.Close();
                        }
                    }
                }
            }
    
            static void SendThreadEntry(object data)
            {
                //等待5s
                Thread.Sleep(5000);
                Socket client = data as Socket;
                String html = String.Format("<span style='color:red; fonst-size:24px;'>{0}</span>", DateTime.Now);
                String response = String.Format(ResponeFormat, html.Length, html);
    
                Console.WriteLine("Send Response");
    
                //发送HTTP回应,本次HTTP请求结束,浏览器此时才接收到网页,在此之前浏览器一直等待
                client.Send(Encoding.UTF8.GetBytes(response));
                client.Close();
            }
        }
    }

    当然,发送Comet.htm的数据不一定启动一个新的线程,可以先将client保存起来(例如保存到全局变量中),等数据准备好了,调用client的Send方法发送数据。

    源代码下载

    本文来自:http://www.cnblogs.com/lucc/archive/2010/05/25/1743877.html

  • 相关阅读:
    hdu 4710 Balls Rearrangement()
    hdu 4707 Pet(DFS水过)
    hdu 4706 Children's Day(模拟)
    hdu 4712 Hamming Distance(随机函数暴力)
    csu 1305 Substring (后缀数组)
    csu 1306 Manor(优先队列)
    csu 1312 榜单(模拟题)
    csu 1303 Decimal (数论题)
    网络爬虫
    Python处理微信利器——itchat
  • 原文地址:https://www.cnblogs.com/ayforver/p/3142768.html
Copyright © 2011-2022 走看看