zoukankan      html  css  js  c++  java
  • C#建立最简单的web服务,无需IIS

    软件架构师何志丹

    本程序仅仅是入门级程序。所以不考虑
    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 + " ");
                    SendStr(coding, "Date: ");
                    SendStr(coding, "Server: httpsrv/1.0 ");
                    SendStr(coding, "MIME-Version: 1.0 ");
                    SendStr(coding, "Content-Type: " + fileType + " ");


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

                    //发送一个空行
                    SendStr(coding, " ");
                }
                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] { ' ', ' ' };
                    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




  • 相关阅读:
    写了一个html5音乐播放器
    跨站脚本攻击之反射型XSS漏洞
    org.hibernate.ObjectNotFoundException异常一则
    addEventListener第二个参数的handleEvent
    IE的fireEvent方法
    DexMongoDB索引优化工具
    javascript 位运算符
    javascript contains方法来判断元素包含关系
    将uglifyjs添加到鼠标右键菜单
    过滤XSS(跨站脚本攻击)的函数和防止svn版本库被浏览
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6905976.html
Copyright © 2011-2022 走看看