软件架构师何志丹

本程序仅仅是入门级程序。所以不考虑

1。多线程。

2,安全性。

3,不考虑端点下载文件。

4,Keep-Alive。

5,不考虑head。

6,为了简洁,删掉了catch的内容。



exe的祖父目录必须有wwwroot目录,且目录有index.htm,内容不限。 

开发环境: WinXP+VS2010C#



一。新建一个项目TestWeb。项目类型:Windows窗体应用程序。

二。新建类RequestProcessor。

 using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

using System.Diagnostics;



namespace TestWeb

{

    class RequestProcessor

    {

        public bool ParseRequestAndProcess(string[] RequestLines)//解析内容

        {

            for (int i = 0; i < RequestLines.Length; i++)

                System.Diagnostics.Trace.Write(RequestLines[i]);



            char[] sp = new Char[1] { ' ' };

            string[] strs = RequestLines[0].Split(sp);

            if (strs[0] == "GET")

            {

                Send(strs[1], 0, 0);

            }



            return false;

        }



        void Send(string filename, long start, long length)//发送文件(文件头和文件)

        {

            string strFileName = GetPathFileName(filename);

            FileStream fs = null;

            try

            {

                fs = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);



            }

            catch (IOException)// FileNotFoundException)

            {//不能将 e.Message,发给浏览器,否则会有安全隐患的

                SendHeadrAndStr("打开文件" + filename + "失败。

");

                return;

            }



            if (length == 0)

                length = fs.Length - start;



            SendHeader("text/html", (fs.Length == length), start, length);

            sendContent(fs, start, length);

        }



        public void SendHeadrAndStr(String str)//直接将str的内容发给html

        {

            byte[] sendchars = Encoding.Default.GetBytes((str).ToCharArray());

            SendHeader("text/html", true, 0, sendchars.Length);

            SendStr(Encoding.Default, str);

        }



        private void SendHeader(string fileType, bool bAll, long start, long length)//发送文件头

        {

            try

            {

                Encoding coding = Encoding.Default;

                string strSend;

                string strState = (bAll) ?

"HTTP/1.1 200 OK" : "HTTP/1.1 206 Partial Content";

                SendStr(coding, strState + "\r\n");

                SendStr(coding, "Date: \r\n");

                SendStr(coding, "Server: httpsrv/1.0\r\n");

                SendStr(coding, "MIME-Version: 1.0\r\n");

                SendStr(coding, "Content-Type: " + fileType + "\r\n");





                strSend = "Content-Length: " + length.ToString();

                SendStr(coding, strSend + "\r\n");



                //发送一个空行

                SendStr(coding, "\r\n");

            }

            catch (ArgumentException)//the request is WRONG

            {





            }



        }



        private void sendContent(FileStream fs, long start, long length)//发生文件内容

        {

            try

            {



                //报文头发送完成,開始发送正文

                const int SOCKETWINDOWSIZE = 8192;

                long r = SOCKETWINDOWSIZE;

                int rd = 0;

                Byte[] senddatas = new Byte[SOCKETWINDOWSIZE];

                fs.Seek(start, SeekOrigin.Begin);

                do

                {

                    r = start + length - fs.Position;

                    //fs.BeginRead(s,s,s,s,d) 以后使用的版本号。用以提高读取的效率                

                    if (r >= SOCKETWINDOWSIZE)

                        rd = fs.Read(senddatas, 0, SOCKETWINDOWSIZE);

                    else

                        rd = fs.Read(senddatas, 0, (int)r);

                    mSockSendData.Send(senddatas, 0, rd, SocketFlags.None);

                } while (fs.Position != start + length);



            }

            catch (SocketException e)

            {

                throw e;

            }

            catch (IOException e)

            {

                throw e;

            }

        }







        public Socket mSockSendData;//Notice: get from ClientSocketThread.s











        private string GetPathFileName(string filename)

        {

            const string strDefaultPage = "index.htm";

            const string strWWWRoot = "..\\..\\wwwroot\\";

            string strFileName = String.Copy(filename);

            if ("/" == strFileName)

                strFileName = strDefaultPage;

            return System.AppDomain.CurrentDomain.BaseDirectory + strWWWRoot + strFileName;

        }



        private void SendStr(Encoding coding, string strSend)//发送一个字符串

        {

            Byte[] sendchars = new Byte[512];

            sendchars = coding.GetBytes((strSend).ToCharArray());

            mSockSendData.Send(sendchars, 0, sendchars.Length, SocketFlags.None);

        }

    }

}



三,新建类ClientSocketThread。

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;



namespace TestWeb

{

    class ClientSocketThread

    {

        public TcpListener tcpl;//Notice: get from SrvMain.tcpl

        private static Encoding ASCII = Encoding.ASCII;



        public void HandleThread()

        {

            Thread currentThread = Thread.CurrentThread;

            try

            {



                Socket s = tcpl.AcceptSocket();





                RequestProcessor aRequestProcessor = new RequestProcessor(); //Notice:

                aRequestProcessor.mSockSendData = s;//Notice: so that the processor can work





                const int BUFFERSIZE = 4096;//that's enough???

Byte[] readclientchar = new Byte[BUFFERSIZE];

                char[] sps = new Char[2] { '\r', '\n' };

                string[] RequestLines = new string[32];



                do

                {

                    //use BUFFERSIZE contral the receive data size to avoid the BufferOverflow attack

                    int rc = s.Receive(readclientchar, 0, BUFFERSIZE, SocketFlags.None);



                    string strReceive = ASCII.GetString(readclientchar, 0, rc);



                    RequestLines = strReceive.Split(sps);





                } while (aRequestProcessor.ParseRequestAndProcess(RequestLines));



                s.Close();

            }

            catch (SocketException)

            {



            }

        }





    }

}





四。主对话框中添加button,按键的对应函数加例如以下代码。

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;



using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Threading;



namespace TestWeb

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }



        private void button1_Click(object sender, EventArgs e)

        {

              try

            {

                //启动监听程序                

                TcpListener tcpl;

                IPAddress LocalIP = Dns.Resolve("localhost").AddressList[0];

                tcpl = new TcpListener(LocalIP, 80); // listen on port 80

                tcpl.Start();

                         



               // int ThreadID = 0;

                while (true)

                {

                    while (!tcpl.Pending())

                    {

                        Thread.Sleep(100);

                    }



                    //启动接受线程

                    ClientSocketThread myThreadHandler = new ClientSocketThread();

                    myThreadHandler.tcpl = tcpl;//Notice: dont forget do this

                    ThreadStart myThreadStart = new ThreadStart(myThreadHandler.HandleThread);

                    Thread myWorkerThread = new Thread(myThreadStart);      

                    myWorkerThread.Start();

                }

            }

            catch (SocketException )

            {

           

            }

            catch (FormatException)

            {

               

            }

            catch (Exception )

            {

               

            }

            //  Console.Read();

       

        }

    }

}

五,启动TestWeb.exe,并单击主对话框上的button。在浏览器中输入:http://127.0.0.1/ 或http://127.0.0.1:80。

源代码下载:

http://download.csdn.net/detail/he_zhidan/8884733

最新文章

  1. 手把手教你写一个RN小程序!
  2. Go语言的堆栈分析
  3. img图片自适应div盒子,前提是不要把盒子的高给写死了,就是不要写高,如下
  4. Ubuntu下安装R语言和开发环境
  5. Win10下Android studio配置
  6. 【代码笔记】iOS-点击出现选择框
  7. 安装PhantomJS
  8. java图片处理——多张图片合成一张Gif图片并播放或Gif拆分成多张图片
  9. VS2010配置目录,解决:error MSB6006: “CL.exe”已退出,代码为 5问题
  10. ssanf()的用法
  11. mysql 索引相关知识
  12. 伪静态 apache重写
  13. paip.jdk1.4 1.5(5.0) 1.6(6.0) 7.0 8.0特点比较与不同
  14. 【Android Developers Training】 60. 在你的UI中显示位图
  15. ISP PIPLINE (十五) AF
  16. 一文掌握 Linux 性能分析之 CPU 篇
  17. C++程序设计方法3:数组下标运算符重载
  18. 温度转换-python
  19. 并发容器——ConcurrentHashMap
  20. vue 缩水版 双向绑定

热门文章

  1. c/s端测试——nw.js篇(selenium工具)
  2. transformer模型解读
  3. 条款23:宁一 non-member no-friend 替换member函数(prefer non-member non-friend functions to members functions)
  4. python基础知识02-序列类型的方法
  5. 大数据学习——hdfs集群启动
  6. ubuntu使用git的时:Warning: Permanently added the RSA host key for IP address &#39;13.250.177.223&#39; to the list of known hosts.
  7. Android广播Broadcast
  8. 【转】php 之 array_filter、array_walk、array_map的区别
  9. django学习之- Models笔记
  10. 为什么utf8占用3个字节