首页 > 编程语言 >C#建立最简单的web服务,无需IIS

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

时间:2022-10-05 11:03:19浏览次数:45  
标签:web fs string IIS C# System length new using

软件架构师何志丹
本程序只是入门级程序,所以不考虑

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。

标签:web,fs,string,IIS,C#,System,length,new,using
From: https://blog.51cto.com/u_15724537/5732405

相关文章

  • VS2005 Debug版,dll /MTd,exe /MDd 跨dll使用CString的链接错误
    dll中导出函数DLL_EXPORTvoidDoString(CString&str);如果exe和dll都是/MD,一切正常如果dll/MTd,exe/MDd则找不到DoString,错误提示:errorLNK2019:无法解析的外部符......
  • vc6.0安装失败解决办法
                                                       ​​何志丹​​---------------------下面的部分是亲身经历安装盘所在目录和安装后......
  • 通信交互 socket套接字 简单通信
    服务端importsockets=socket.socket()s.bind(('0.0.0.0',1234))#主机ip,端口号s.listen()#等待连接c,addr=s.accept()#等待连接print(c)print(addr)客户端import......
  • python socket 网页爬虫
    importsocket#第一步获取域名或ip地址host='www.baidu.com'port=80header=b'GET/HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:close\r\n\r\n'#第二步域......
  • 引擎之旅 Chapter.4 日志系统
    关于近段时间为何没有更新的解释:Findanewjob.目录引言日志语句的分类控制台窗体和VSOutputTab的日志打印存储至特定的文件中展示堆栈信息引言一般来说,一个优质......
  • cygwin的下的gcc的一点体会。
    cygwin的下的gcc的一点体会。1,源文件的扩展名为c,按C的规则编译;源文件的扩展名为cpp,按C++的规则编译。注意:两者默认包括的文件也不同。2,gcc-ohe......
  • CAP 介绍
    https://github.com/dotnetcore/caphttps://www.cnblogs.com/savorboard/作者博客CAP是一个基于.Net标准的库,是处理分布式事务的解决方案,具有EventBus的功能,轻量级、易......
  • vue nextTick的用法
    一、什么是vue.nextTick()定义:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。所以就衍生出了这个获取更新后的DOM......
  • webpack性能优化有哪些方法?
    线程加载器多线程可以提高程序运行效率,在webpack中使用thread-loader(一个启动多线程的加载器)npmithread-loader-D配置{test:/\.js$/,use:[......
  • GCC Arm 11.3rel1, 12.2编译提示 _close is not implemented and will always fail
    使用GCCArm工具链开发的项目,在11.2下编译正常,但是升级到arm-gnu-toolchain-11.3.rel1以及arm-gnu-toolchain-12.2之后,编译出现警告/opt/gcc-arm/arm-gnu-toolc......