关于HTTP协议的具体内容,前面章节已经有所讲解,相信读者已有所了解,在此不在累述,本章节讲解自定义web服务器。

 一,.net提供自定义Web服务器的类

以下只是写主要的类

1.HTTPListener:对TCPListener的封装

2.TCPListener:对Socket的封装

3.Socket:对协议栈传输层接口的封装

 二,用.net提供的类进行web服务器的自定义

1.用HTTPListener

using System;
using System.Net;
using System.IO;
using System.Text;
using System.Globalization;
using System.Threading; namespace Microsoft.Samples.HttpListener
{
static class HttpRequestListener
{
public static void Main()
{
string[] prefixes = new string[];
prefixes[] = "http://localhost:8080/";
ProcessRequests(prefixes);
} private static void ProcessRequests(string[] prefixes)
{
if (!System.Net.HttpListener.IsSupported)
{
Console.WriteLine(
"Windows XP SP2, Server 2003, or higher is required to " +
"use the HttpListener class.");
return;
}
// URI prefixes are required,
if (prefixes == null || prefixes.Length == )
throw new ArgumentException("prefixes"); // Create a listener and add the prefixes.
System.Net.HttpListener listener = new System.Net.HttpListener();
Thread handleRequest = null;
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
} try
{
// 启动监听,开始监听请求
listener.Start();
Console.WriteLine("Listening..."); while(true)
{
HttpListenerResponse response = null; // GetContext 在等待一个请求时将阻塞 .
HttpListenerContext context = listener.GetContext(); handleRequest = new Thread(delegate()
{
try
{
Console.WriteLine("当前线程是否为线程池线程:" + (Thread.CurrentThread.IsThreadPoolThread==true?"是":"否"));
Console.WriteLine("当前线程总数:" + System.Diagnostics.Process.GetCurrentProcess().Threads.Count.ToString());
response = context.Response; string responseBody =
"<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
responseBody += "<input type='button' value='js测试' id='test1' onclick='test();'/><br/><input type='submit' value='提交测试' id='test2' /></form></BODY></HTML>";
string responseHeader =
string.Format(
"Content-Type: text/html; charset=UTf-8;Content-Length: {0}", responseBody.Length); byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);
response.ContentLength64 = responseBodyBytes.Length;
System.IO.Stream output = response.OutputStream;
// 向客户端发送回应头信息
response.Headers.Add(responseHeader);
// 向客户端发送状态行
response.StatusCode = (int)HttpStatusCode.OK;
response.ProtocolVersion = Version.Parse("1.1");
// 想客户端发送主体部分
output.Write(responseBodyBytes, , responseBodyBytes.Length);
}
catch (HttpListenerException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (response != null)
response.Close();
}
Thread.Sleep();
});
handleRequest.Start();
}
}
catch (HttpListenerException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
//停止监听
listener.Close();
Console.WriteLine("Done Listening.");
}
}
}
}

服务端运行效果:

客户端运行效果:

2.用TCPListener

  private static void  ProcessRequestsWithTcpListener()
{
TcpListener server=new TcpListener(IPAddress.Any,); server.Start(); Console.WriteLine("HTTP Server Start Listening...."); while (true)
{
TcpClient client = server.AcceptTcpClient();
Thread handleRequest = new Thread(delegate()
{
try
{
NetworkStream inputoutputstream = client.GetStream();
Byte[] buffer = new Byte[];
int readLength = inputoutputstream.Read(buffer, , buffer.Length);
String inputoutputstring = Encoding.ASCII.GetString(buffer, , readLength); Console.WriteLine("客户端信息:" + client.Client.RemoteEndPoint);
Console.WriteLine("客户端请求信息:\n" + inputoutputstring); String statusLine = "HTTP/1.1 200 OK\r\n";
string responseBody =
"<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
responseBody += "<input type='button' value='js测试' id='test1' onclick='test();'/><br/><input type='submit' value='提交测试' id='test2' /></form></BODY></HTML>";
string responseHeader =
string.Format(
"Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n", responseBody.Length + statusLine.Length);
byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine);
byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody); // 写入状态行信息
inputoutputstream.Write(responseStatusLineBytes, , responseStatusLineBytes.Length);
// 写入回应的头部
inputoutputstream.Write(responseHeaderBytes, , responseHeaderBytes.Length);
// 写入回应头部和内容之间的空行
inputoutputstream.Write(new byte[] { , }, , ); // 写入回应的内容
inputoutputstream.Write(responseBodyBytes, , responseBodyBytes.Length);
}
catch (Exception ex)
{
Console.WriteLine("异常信息:"+ex.Message);
}
finally
{
// 关闭与客户端的连接
client.Close();
} });
handleRequest.Start();
}
}

服务端运行效果:

客户端运行效果:和1类似

3.用Socket

 private static void ProcessRequestsWithSocket()
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, ));
server.Listen(); Console.WriteLine("HTTP Server Start Listening...."); while (true)
{
Socket client = server.Accept();
Thread handleRequest = new Thread(delegate()
{
try
{
Byte[] buffer = new Byte[];
int readLength = client.Receive(buffer, buffer.Length,SocketFlags.None);
String inputoutputstring = Encoding.ASCII.GetString(buffer, , readLength); Console.WriteLine("客户端信息:" + client.RemoteEndPoint);
Console.WriteLine("客户端请求信息:\n" + inputoutputstring); String statusLine = "HTTP/1.1 200 OK\r\n";
string responseBody =
"<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
responseBody += "<input type='button' value='js测试' id='test1' onclick='test();'/><br/><input type='submit' value='提交测试' id='test2' /></form></BODY></HTML>";
string responseHeader =
string.Format(
"Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n", responseBody.Length + statusLine.Length);
byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine);
byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody); // 写入状态行信息
client.Send(responseStatusLineBytes);
// 写入回应的头部
client.Send(responseHeaderBytes);
// 写入回应头部和内容之间的空行
client.Send(new byte[] { , }); // 写入回应的内容
client.Send(responseBodyBytes);
}
catch (Exception ex)
{
Console.WriteLine("异常信息:" + ex.Message);
}
finally
{
// 关闭与客户端的连接
client.Close();
} });
handleRequest.Start();
}
}

服务端和客户端运行效果和2类似.
    声明:2和3代码修改自:http://www.cnblogs.com/zhili/archive/2012/08/23/WebServer.html 只为交流,不为商用.

备注:面试时,常问的一个问题是:http中post和get请求的区别

个人感觉:1.两者传输方式不同,post将数据放在请求内容里传输,get放在请求行传输

2.post内容没有大小限制,get内容有大小限制。

自定义web服务器(四)的更多相关文章

  1. atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener

    atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty  HttpListener 1. 自定义web服务器的实现方案,基于原始socket vs   ...

  2. 网络知识 - 简易的自定义Web服务器

    简易的自定义Web服务器 基于浏览器向服务端发起请求 两台主机各自的进程之间相互通信,需要协议.IP地址和端口号,IP表示了主机的网络地址,而端口号则表示了主机上的某个进程的地址,IP加Port统称为 ...

  3. [C# 网络编程系列]专题三:自定义Web服务器

    转自:http://www.cnblogs.com/zhili/archive/2012/08/23/2652460.html 前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网 ...

  4. 转:【专题三】自定义Web服务器

    前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网络中的协议有了大致的了解的, 本专题将针对HTTP协议定义一个Web服务器,我们平常浏览网页通过在浏览器中输入一个网址就可以看到 ...

  5. 专题三:自定义Web服务器

    前言: 经过前面的专题中对网络层协议和HTTP协议的简单介绍相信大家对网络中的协议有了大致的了解的, 本专题将针对HTTP协议定义一个Web服务器,我们平常浏览网页通过在浏览器中输入一个网址就可以看到 ...

  6. ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上

    一.前言 大家都知道,在之前,我们Asp.net 的网站都只能部署在IIS上,并且IIS也只存在于Windows上,这样Asp.net开发的网站就难以做到跨平台.由于微软的各项技术的开源,所以微软自然 ...

  7. net网站运行在自定义的Web服务器上

    ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上   一.前言 大家都知道,在之前,我们Asp.net 的网站都只能部署在IIS上,并且IIS也只存在于Win ...

  8. nginx 隐藏版本号与WEB服务器信息

    nginx不仅可以隐藏版本信息,还支持自定义web服务器信息 先看看最终的隐藏结果吧 具体怎么实现呢,其实也很简单,请往下看 1 官网下载最新稳定版 wget http://nginx.org/dow ...

  9. Visual Studio中用于ASP.NET Web项目的Web服务器

    当您在 Visual Studio 中开发 Web 项目时,需要 Web 服务器才能测试或运行它们. 利用 Visual Studio,您可以使用不同的 Web 服务器进行测试,包括 IIS Expr ...

随机推荐

  1. jQuery 1.7以后 jQuery2 新元素绑定事件on替代live

    最近做了一个类别动态加载的功能,jQuery版本用的是2.02. 绑定事件jQuery1.7之前用的是live或者是bind.新版的jQuery新增了on方法 由于子类别是动态加载的,默认是不会有事件 ...

  2. tail报错

    在block和index都没有满的情况下,有如下报错: tail -f messages tail:cannot watch 'messages' : No space left on device ...

  3. 转 修改oracle用户密码永不过期

      1.查看用户的proifle是哪个,一般是default: sql>SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的 ...

  4. 2015版App推广全攻略(完整版)

    线上渠道 1.基础上线 各大手机厂商市场.第三方应用商店.大平台.PC下载站.手机WAP站.收录站.移动互联网应用推荐媒体等等基本可以覆盖Android版本发布渠 道:推广的第一步是要上线,这是最基础 ...

  5. 【pyhton】【转】修改递归次数

    import sys sys.setrecursionlimit(1500) # set the maximum depth as 1500 def recursion(n): if(n <= ...

  6. IOS中如何判断APP是否安装后首次运行或升级后首次运行

    对于是否为首次安装的App可以使用如下方法来判断 [[NSUserDefaults standardUserDefaults] boolForKey:@"firstLaunch"] ...

  7. Anagrams问题

    #include<stdio.h> #include<string.h> int main() { int i; ],word2[]; //分别用于存储输入的两个单词 int ...

  8. C语言基础知识-循环结构

    用while打印出1~100之间7的倍数    int i = 1;     while循环是当条件表达式的结果为真时,执行大括号里面的循环体,重复执行直到条件表达式的结果为假时结束循环.     w ...

  9. C++ new operator, delete operator, operator new, operator delete, new placement

    http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/arch ...

  10. 1010 [HNOI2008]玩具装箱toy

    斜率优化dp: 推荐学习http://www.cnblogs.com/perseawe/archive/2012/05/12/bz1010.html 看着别人的题解自己学着推,终于理解了 #inclu ...