关于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. [leetcode] 405. Convert a Number to Hexadecimal

    https://leetcode.com/contest/6/problems/convert-a-number-to-hexadecimal/ 分析:10进制转换成16进制,不能用库函数,刚开始,我 ...

  2. n个骰子的点数

    把n个骰子扔在地上,所有骰子朝上的一面的点数之和为s.输入n,打印出s的所有可能的值和出现的概率. 解法一:基于递归求骰子点数. /////////////////基于递归求骰子点数///////// ...

  3. linux命令行下命令参数前的一横(-)和两横(--)的区别

    原文转自:http://blog.csdn.net/songjinshi/article/details/6816776 在解释这些区别之前我们先了解一下有关linux的背景知识,这个需要大家先认真看 ...

  4. centos下如何用SMplayer播放WMV格式文件

    安装的是centos6.6,想用来做桌面系统使用!! 装完后,其他的办公软件都安装好了.但是,视频播放却出问题了. 配置的yum安装的SMplayer播放器,播放其他的视频文件没问题,就是WMV的视频 ...

  5. aspx与mvc页面验证码

    验证码类代码 using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Dr ...

  6. 盗链网易163、腾讯QQ、新浪sina、百度Baidu的图片之PHP独立版

    网易相册频道,网易相册确实是一个高质量图片的地方,而且免费,唯一缺点是很多加了水印,但这个不重要了,无意间发现网易163相册频道的图片是防止盗链的,于是便自己写了一个小程序来突破这个. 本盗链图片最新 ...

  7. cms开发笔记2

    1 创建数据库表 //配置文件CREATE TABLE IF NOT EXISTS `mc_config` ( `en_name` varchar(80) NOT NULL, `ch_name` va ...

  8. 1.0 基础、标示符、常量、数据类型(enum 枚举,struct 结构体)、操作符、循环、数组

    一.程序 现实生活中,程序是指完成某些事务的一种既定方法和过程,可以把程序看成是一系列动作执行过程的描述. 在计算机世界,程序是指令,即为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集 ...

  9. Kinetic使用注意点--blob

    new Blob(config) 参数: config:包含所有配置项的对象. { points: "存放路径点的数组,可以用一层数组[a,b,c,d].二层数组[[a,b],[c,d]]或 ...

  10. 移动端Reactive Native轮播组件

    移动端Reactive Native轮播组件 总结下这段时间学习reactive native的一些东西,我们来认识一下,被炒得这么火的rn,究竟是个什么东西,以及如何去搭建自己的demo. reac ...