C#建立最简单的web服务,无需IIS

简介: 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 + "\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)
            {
            }
        }
    }
}


四,主对话框中增加按钮,按键的相应函数加如下代码。

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,并单击主对话框上的按钮。在浏览器中输入:http://127.0.0.1/http://127.0.0.1:80



源码下载:


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



相关文章
|
24天前
|
XML JSON 数据安全/隐私保护
Web服务
【10月更文挑战第18天】Web服务
43 9
|
24天前
|
XML JSON 安全
Web服务是通过标准化的通信协议和数据格式
【10月更文挑战第18天】Web服务是通过标准化的通信协议和数据格式
144 69
|
6天前
|
Go UED
Go Web服务中如何优雅平滑重启?
在生产环境中,服务升级时如何确保不中断当前请求并应用新代码是一个挑战。本文介绍了如何使用 Go 语言的 `endless` 包实现服务的优雅重启,确保在不停止服务的情况下完成无缝升级。通过示例代码和测试步骤,详细展示了 `endless` 包的工作原理和实际应用。
22 3
|
7天前
|
JSON Go UED
Go Web服务中如何优雅关机?
在构建 Web 服务时,优雅关机是一个关键的技术点,它确保服务关闭时所有正在处理的请求都能顺利完成。本文通过一个简单的 Go 语言示例,展示了如何使用 Gin 框架实现优雅关机。通过捕获系统信号和使用 `http.Server` 的 `Shutdown` 方法,我们可以在服务关闭前等待所有请求处理完毕,从而提升用户体验,避免数据丢失或不一致。
14 1
|
13天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
24天前
|
XML JSON 安全
定义Web服务
【10月更文挑战第18天】定义Web服务
55 12
|
1月前
|
前端开发 Java API
JAVA Web 服务及底层框架原理
【10月更文挑战第1天】Java Web 服务是基于 Java 编程语言用于开发分布式网络应用程序的一种技术。它通常运行在 Web 服务器上,并通过 HTTP 协议与客户端进行通信。
23 1
|
1月前
|
应用服务中间件 网络安全 nginx
nginx作为web服务以及nginx.conf详解
nginx作为web服务以及nginx.conf详解
|
1月前
|
XML 关系型数据库 MySQL
Web Services 服务 是不是过时了?创建 Web Services 服务实例
本文讨论了WebServices(基于SOAP协议)与WebAPI(基于RESTful)在开发中的应用,回顾了WebServices的历史特点,比较了两者在技术栈、轻量化和适用场景的差异,并分享了使用VB.net开发WebServices的具体配置步骤和疑问。
20 0
|
1月前
|
云安全 SQL 安全
数字时代下的Web应用程序安全:漏洞扫描服务的功能与优势
在当今这个数字化时代,Web应用程序不仅是企业与用户之间互动的桥梁,更是企业展示服务、传递价值的核心平台。然而,随着技术的不断进步,Web应用程序的复杂性也在不断增加,这为恶意攻击者提供了可乘之机。安全漏洞的频发,如SQL注入、跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等,严重威胁着企业的数据安全、服务稳定性乃至经济利益。在这样的背景下,漏洞扫描服务作为一道重要的安全防线,显得尤为重要。本文将深入探讨漏洞扫描服务在面对Web应用程序安全问题时,所具备的功能优势。