简单web服务器学习总结
生活随笔
收集整理的這篇文章主要介紹了
简单web服务器学习总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
用node.js實現簡單的web服務器
http://www.cnblogs.com/loogn/p/3362475.htmlhttp模塊已提供了基本功能,所以我主要解決兩個問題,1是靜態資源的處理,2是動態資源的路由。
靜態資源在node.js里的意思是不變的,如圖片、前端js、css、html頁面等。
動態資源我們一般指aspx頁面,ashx頁面,asp頁面,jsp頁面,php頁面等,而node.js里其實沒動態資
源這一說,它對請求的處理都是由回調方法完成的,在我實現的httserver里,借鑒了ashx的寫法,把處
理請求的js文件看作動態資源。
首先實現一個處理靜態資源的函數,其實就是對本地文件的讀取操作,這個方法已滿足了上面說的靜態
資源的處理。
//處理靜態資源
function staticResHandler(localPath, ext, response) {
? ? fs.readFile(localPath, "binary", function (error, file) {
? ? ? ? if (error) {
? ? ? ? ? ? response.writeHead(500, { "Content-Type": "text/plain" });
? ? ? ? ? ? response.end("Server Error:" + error);
? ? ? ? } else {
? ? ? ? ? ? response.writeHead(200, { "Content-Type": getContentTypeByExt(ext) });
? ? ? ? ? ? response.end(file, "binary");
? ? ? ? }
? ? });
}
而動態資源肯定不能一個方法搞定,就像你的網站有register.aspx、login.aspx等等,都需要你自己來
寫,在我的httpserver里,每個處理請求的js模塊都導出processRequest(request,response)即可,比
如實現一個register.js(只輸出字符串register)
exports.processRequest = function (request, response) {
? ? response.writeHead(200, { 'Content-Type': 'text/plain' });
? ? resp.end("register");
}
現在當請求到來時,我們要做的就是決定怎么處理,即路由。
因為靜態資源url指定靜態資源大家都很習慣了,所以這里不變,比如
訪問http://localhost/img/logo.png ?就是訪問 web根目錄\img\logo.png;
訪問http://localhost/js/what.js 就是訪問 web根目錄\js\what.js;
而動態資源也是一般的js文件,即服務器端js,就比如我實現的這個httpserver.js和上面說的
register.js都是不應該讓用戶訪問的,所以路由的時候要判斷,就是一些if、else,簡單而強大是我的
最愛,這里只看最后的的判斷,
fs.exists(localPath, function (exists) {
? ? if (exists) {
? ? ? ? if (staticRes) {
? ? ? ? ? ? staticResHandler(localPath, ext, response); //靜態資源
? ? ? ? } else {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? <strong><span style="color: #008000;">var handler = require
(localPath);</span></strong>
? ? ? ? ? ? ? ? if (handler.processRequest && typeof handler.processRequest === 'function')?
{
? ? ? ? ? ? ? ? ? ? <span style="color: #008000;"><strong>handler.processRequest(request,?
response);</strong></span> //動態資源
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? response.writeHead(404, { 'Content-Type': 'text/plain' });
? ? ? ? ? ? ? ? ? ? response.end('404:Handle Not found');
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (exception) {
? ? ? ? ? ? ? ? console.log('error::url:' + request.url + 'msg:' + exception);
? ? ? ? ? ? ? ? response.writeHead(500, { "Content-Type": "text/plain" });
? ? ? ? ? ? ? ? response.end("Server Error:" + exception);
? ? ? ? ? ? }
? ? ? ? }
? ? } else { //資源不存在
? ? ? ? response.writeHead(404, { 'Content-Type': 'text/plain' });
? ? ? ? response.end('404:File Not found');
? ? }
});
處理靜態資源上面已說過了,請看處理動態資源的那兩句,localPath是相對web根目錄的后端js的路徑
,如果上面register.js在 根目錄/src/account文件夾里,那么你的url請求就是
http://localhost/account/register,而這時localPath就是./src/account/register.js,注意這里不
是MVC,只是url沒有src路徑和.js后綴而已,那么為什么要這樣呢?就是為了和前端js文件區分開!
再有,沒有配置的程序不是好程序,不過我的配置總是很爛的配置!(你可能感覺我寫的很亂,不過沒
關系,后面給出完整代碼,看一下就清楚了,如果你感覺不錯,下載了事例在你電腦上運行了,那我也
倍感榮幸了!)
//配置
var config = {
? ? port: 80,
? ? denyAccess: ['./httpserver.js', './src/requirecache.js'],
? ? localIPs: ['127.0.0.1'],
? ? srcpath: '/src'
};
./src/requirecache.js這個文件是干什么的呢?這里要說明一下,require這個方法是有緩存機制的,
它把加載過的模塊都緩存到require.cache這個對象中,當第二次require的時候就直接回返緩存的模塊
了,當然這樣是為性能考慮,但是我修改一下register.js是不想重啟web服務器的,如果你感覺無所謂
,那這個特殊的動態資源就不需要了,請明白,requirecache.js和register.js是被一樣看待的,都是
處理請求的js文件。requirecache.js模塊的功能就是刪除模板緩存:
var querystring=require('querystring');
var url=require('url');
?
exports.processRequest = function (request, response) {
? ? response.writeHead(200, { 'Content-Type': 'text/html' });
? ? var qs= querystring.parse(url.parse(request.url).query);
? ? if(qs.key){
? ? ? ? delete require.cache[qs.key];
? ? }
? ? response.write('<html><head></head><body>');
? ? for(var key in require.cache){
? ? ? ? response.write('<a href="?key='+key+'">'+key+'</a><br/>');
? ? }
? ? response.write('<a href="?">View</a><br/>');
? ? response.end('</body></html>'); ??
}
運行了node httpserver.js后,打開http://localhost/requirecache大概是這樣:
然后就是刪哪個點哪個就可以(對于httpserver.js來說,是一個很實用小功能)。
源代碼有兩個文件:
httpserver.js(這個是必須的)
?httpserver.js
requirecache.js(這個是很有用的,要放到config.srcpath路徑下)
?requirecache.js
完成例子下載?
========
nodejs簡單搭建web服務器 ?
http://blog.163.com/liuyong_xiaxia/blog/#m=0? ? ? nodejs是可以作為前端語言的服務器,采用事件驅動,速度快、性能好。他可以不用像tomcat那
么復雜的配置、直接部署前端應用。
? ? ? ? 首先到官網下載相應的版本https://nodejs.org/,安裝到本地機器上面。
? ? ? ? 然后進入安裝目錄、把做好的配置文件(server.js)放到安裝目錄下面。
? ? ? ? 再進入命令模式、到安裝目錄、執行node server,此時它會提示你缺少一些模塊,缺少什么安
裝什么就可以,npm install XXX -g(表示全局安裝,不用-g表示就安裝到安裝目錄modules下)。
? ? ? ? ?模塊安裝完成后、再執行node server命令,沒任何錯誤表示啟動成功,可以到瀏覽器直接訪
問。
? ? ?具體server.js如下,其中connect、serve-static就表示node服務需要依賴的模塊。路徑表示你前
端應用所在的路徑,端口表示node服務要監聽的端口。
var connect = require('connect');
var serveStatic = require('serve-static');
var server = connect();
server.use(serveStatic('E:/work/workspace/public'));
server.listen(8080);
========
boa服務器
BOA 服務器是一個小巧高效的web服務器,是一個運行于unix或linux下的,支持CGI的、適合于嵌入式系
統的單任務的http服務器,源代碼開放、性能高。
目錄
1 Boa
2 CGI
Boa
是一種非常小巧的Web服務器,其可執行代碼只有大約60KB左右。作為一種單任務Web服務器,Boa只能依
次完成用戶的請求,而不會fork出新的進程來處理并發連接請求。但Boa支持CGI,能夠為CGI程序fork出
一個進程來執行。Boa的設計目標是速度和安全。
CGI
在物理上是一段程序,運行在服務器上,提供同客戶端HTML頁面的接口。即客戶端與服務器的接口。
比如留言本的工作流程:先由用戶在客戶端輸入一些信息,如名字之類的東西。接著用戶按一下“留言
”(到目前為止工作都在客戶端),瀏覽器把這些信息傳送到服務器的CGI目錄下特定的cgi程序中,于
是cgi程序在服務器上按照預定的方法進行處理。在本例中就是把用戶提交的信息存入指定的文件中。然
后cgi程序給客戶端發送一個信息,表示請求的任務已經結束。此時用戶在瀏覽器里將看到“留言結束”
的字樣。整個過程結束。
========
最簡單的web服務器
http://www.cnblogs.com/qiaoyang/archive/2011/10/26/2225559.html通過Socket編程創建一個簡單的web服務器。這個服務器通過80號端口提供訪問,向瀏覽器返回一個固定
的靜態頁面。此示例中請求的消息由瀏覽器生成,并發送到服務器,這個程序將簡單地顯示請求的消息
。回應的消息由服務器程序生成,通過Socket傳輸返回給瀏覽器。
public class SimpleSocketListener
? ? {
? ? ? ? public void Run()
? ? ? ? {
? ? ? ? ? ? // 取得本機的 loopback 網絡地址,即 127.0.0.1
? ? ? ? ? ? IPAddress address = IPAddress.Loopback;
? ? ? ? ? ? // 創建可以訪問的端點,8001 表示端口號
? ? ? ? ? ? IPEndPoint endPoint = new IPEndPoint(address,8001);
? ? ? ? ? ? // 創建一個 socket,使用 IPv4 地址,傳輸控制協議 TCP,雙向、可靠、基于連接的字
節流
? ? ? ? ? ? Socket socket = new Socket(
? ? ? ? ? ? ? ? AddressFamily.InterNetwork,
? ? ? ? ? ? ? ? SocketType.Stream,
? ? ? ? ? ? ? ? ProtocolType.Tcp);
? ? ? ? ? ? // 將 socket 綁定到一個端點上
? ? ? ? ? ? socket.Bind(endPoint);
? ? ? ? ? ? // 設置連接隊列的長度
? ? ? ? ? ? socket.Listen(10);
? ? ? ? ? ? Console.WriteLine("開始監聽, 端口號:{0}.", endPoint.Port);
? ? ? ? ? ? while (true)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? // 開始監聽,這個方法會阻塞線程的執行,直到接受到一個客戶端的連接請求
? ? ? ? ? ? ? ? Socket client = socket.Accept();
? ? ? ? ? ? ? ? // 輸出客戶端的地址
? ? ? ? ? ? ? ? Console.WriteLine(client.RemoteEndPoint);
? ? ? ? ? ? ? ? // 準備讀取客戶端請求的數據,讀取的數據將保存在一個數組中
? ? ? ? ? ? ? ? byte[] buffer = new byte[4096];
? ? ? ? ? ? ? ? // 接受數據
? ? ? ? ? ? ? ? int length = client.Receive(buffer, 4096, SocketFlags.None);
? ? ? ? ? ? ? ? // 將請求的數據翻譯為 UTF-8
? ? ? ? ? ? ? ? System.Text.Encoding utf8 = System.Text.Encoding.UTF8;
? ? ? ? ? ? ? ? string requestString = utf8.GetString(buffer, 0, length);
? ? ? ? ? ? ? ? // 顯示請求的內容
? ? ? ? ? ? ? ? Console.WriteLine(requestString);
? ? ? ? ? ? ? ? // 狀態行
? ? ? ? ? ? ? ? string statusLine = "HTTP/1.1 200 OK\r\n";
? ? ? ? ? ? ? ? byte[] statusLineBytes = utf8.GetBytes(statusLine);
? ? ? ? ? ? ? ? // 準備發送到客戶端的網頁
? ? ? ? ? ? ? ? string responseBody
? ? ? ? ? ? ? ? ? ? = @"<html>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <head><title>From Socket Server</title></head>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <body><h1>Hello, world.</h1></body>
? ? ? ? ? ? ? ? ? ? ? ? </html>";
? ? ? ? ? ? ? ? byte[] responseBodyBytes = utf8.GetBytes(responseBody);
? ? ? ? ? ? ? ? // 回應的頭部
? ? ? ? ? ? ? ? string responseHeader =
? ? ? ? ? ? ? ? ? ? string.Format(
? ? ? ? ? ? ? ? ? ? ? ? "Content-Type: text/html; charset=UTF-8\r\nContent-Length: {0}\r
\n",
? ? ? ? ? ? ? ? ? ? ? ? responseBody.Length
? ? ? ? ? ? ? ? ? ? ? ? );
? ? ? ? ? ? ? ? byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);
?
? ? ? ? ? ? ? ? // 向客戶端發送狀態信息
? ? ? ? ? ? ? ? client.Send(statusLineBytes);
? ? ? ? ? ? ? ? // 向客戶端發送回應頭
? ? ? ? ? ? ? ? client.Send(responseHeaderBytes);
? ? ? ? ? ? ? ? // 頭部與內容的分隔行
? ? ? ? ? ? ? ? client.Send(new byte[] { 13, 10 });
? ? ? ? ? ? ? ? // 向客戶端發送內容部分
? ? ? ? ? ? ? ? client.Send(responseBodyBytes);
?
? ? ? ? ? ? ? ? // 斷開與客戶端的連接
? ? ? ? ? ? ? ? client.Close();
? ? ? ? ? ? ? ? if (Console.KeyAvailable)
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? // 關閉服務器
? ? ? ? ? ? socket.Close();
? ? ? ? }
? ? }
在瀏覽器的窗口中輸入服務器的地址:http://127.0.0.1:8001,則瀏覽器中可以看到如圖所示效果。
========
最簡單的Web服務器
http://www.cnblogs.com/wlitsoft/archive/2012/04/24/2467652.html本案例中應用到得一些類和方法先一一列出來
1.IPAddress類用來表示一個IP地址
1.1 IPAddress.Parse("192.168.43.104") 將一串ip地址字符串轉換為IP地址
1.2 IPAddress.Loopback ?獲得本機回環地址 即:127.0.0.1
2.IPEndPoint類(端點) 說白了就是ip地址和端口的組合(IP:Point) 他能唯一確定網絡中的一臺電
腦的某一個應用程序
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.43.104"), 8080); //創建了
一個ip地址為192.168.43.104端口號位8080的網絡端點
2.1.1 Address 獲取或設置終結點的 IP 地址 ? ex:endPoint.Address ?//192.168.43.104
2.1.2 AddressFamily 獲得網絡協議 ? ? ? ? ? ? ?ex:endPoint.AddressFamily ?//http
2.1.3 AddressPoint ? 獲得端口號信息 ? ? ? ? ?ex:endPoint.Point ? //8080
3.Socket類 ? ?位于System.Net.Socket命名空間中 ? ?其封裝了Socket(套接字)的操作。
3.1 Listen 設置基于連接通信的socket進入監聽狀態,并設置等待隊列的長度。 ?ex:
socket.Listen(10) ?//只允許10個客戶端同時發生請求
3.2 Accept 等待一個新的連接,當新的連接到達的時候,返回一個針對新連接的Socket對象。即每
個建立連接的客戶端都對應有一個Socket對象在服務器端,客戶端通過這個對象就可以和服務端進行連
接通信了。 ? ?ex: ? Socket client = socket.Accept();
3.3 Receive 通過Socket接受字節數據,保存到一個字節數據中,返回一個int型的數據(實際接收
的字節數)。
ex://新建一個緩沖區
? ? ? ? ? ? ? ? byte[] buffer = new byte[2048];
? ? ? ? ? ? ? ? //接受數據
? ? ? ? ? ? ? ? int length = client.Receive(buffer,buffer.Length,SocketFlags.None);
3.4 Send 故名思議 就是發送數據吧 沒錯 ?send通過Socket發送預先保存在字節數組中的數據。
下面是完整的事例代碼:
//----------------------------------------------------------------------------------------
? ? ? ? ? ? IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.43.104"), 8080);
? ? ? ? ? ? //創建socket,使用ipv4地址,傳輸協議為tcp,雙向、可靠、基于連接的字節流
? ? ? ? ? ? Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,?
ProtocolType.Tcp);
? ? ? ? ? ? //將其綁定到一個端點上
? ? ? ? ? ? socket.Bind(endPoint);
? ? ? ? ? ? //設置連接隊列的長度
? ? ? ? ? ? socket.Listen(10);
? ? ? ? ? ? Console.WriteLine("開始監聽,端口號:{0}",endPoint.Port);
? ? ? ? ? ? while (true)
? ? ? ? ? ? {?
? ? ? ? ? ? ? ? //開始監聽。這個方法阻塞線程執行,直到接受到一個客戶端的連接請求
? ? ? ? ? ? ? ? Socket client = socket.Accept();
? ? ? ? ? ? ? ? //輸出客戶端地址
? ? ? ? ? ? ? ? Console.WriteLine("客戶端地址:{0}",client.RemoteEndPoint);
? ? ? ? ? ? ? ? //新建一個緩沖區
? ? ? ? ? ? ? ? byte[] buffer = new byte[2048];
? ? ? ? ? ? ? ? //接受數據
? ? ? ? ? ? ? ? int length = client.Receive(buffer,buffer.Length,SocketFlags.None);
? ? ? ? ? ? ? ? //將請求的數據轉換為utf-8
? ? ? ? ? ? ? ? //Encoding utf8 = Encoding.UTF8;
? ? ? ? ? ? ? ? string requestString = Encoding.UTF8.GetString(buffer, 0, length);
? ? ? ? ? ? ? ? //顯示請求的消息
? ? ? ? ? ? ? ? Console.WriteLine(requestString);
? ? ? ? ? ? ? ? //回應的狀態行
? ? ? ? ? ? ? ? string statusLine = "HTTP/1.1 200 OK\r\n";
? ? ? ? ? ? ? ? byte[] statusLineBytes = Encoding.UTF8.GetBytes(statusLine);
? ? ? ? ? ? ? ? //準備發送到客戶端的網頁
? ? ? ? ? ? ? ? string responseBody = "<html><head><title>hello?
world</title></head><body><h2>Hello World</h2></body></html>";
? ? ? ? ? ? ? ? byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);
? ? ? ? ? ? ? ? //回應的頭部
? ? ? ? ? ? ? ? string responseHeader = string.Format("Content-type:text/html;charset=UTF-
8\r\nContent-Length:{0}\r\n", responseBody.Length);
? ? ? ? ? ? ? ? byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
? ? ? ? ? ? ? ? client.Send(statusLineBytes); ? //發送狀態信息
? ? ? ? ? ? ? ? client.Send(responseHeaderBytes); ?//發送回應頭
? ? ? ? ? ? ? ? client.Send(new byte[] { 13, 10 }); //頭部與內容的分割行
? ? ? ? ? ? ? ? client.Send(responseBodyBytes); ? //發送內容部分
? ? ? ? ? ? ? ? client.Close(); ? //斷開與客戶端的連接
? ? ? ? ? ? ? ? if (Console.KeyAvailable)
? ? ? ? ? ? ? ? ? ? break; ? ?//跳出死循環
? ? ? ? ? ? ? ??
? ? ? ? ? ? }
? ? ? ? ? ? //關閉服務器
? ? ? ? ? ? socket.Close();
因為http協議是無狀態連接,所以每完成一次或多次請求服務器會自動與客戶端斷開連接,保持服務器
的資源
運行結果:
本文源代碼點擊下載
========
C#建立最簡單的web服務,無需IIS
http://blog.csdn.net/he_zhidan/article/details/46820215本程序只是入門級程序,所以不考慮
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
========
總結
以上是生活随笔為你收集整理的简单web服务器学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql存储过程调试学习总结
- 下一篇: 图解Detours实例