本程序只是入门级程序,所以不考虑1,多线程。2,安全性。3,不考虑端点下载文件。4,Keep-Alive。5,不考虑head。6,为了简洁,删掉了catch的内容。 开发环境: WinXP+VS2010C#
序列号 | CPU | RAM | HDD | 带宽 | 售价(美元) | 免费试用 |
---|---|---|---|---|---|---|
香港服务器1 | E5-2620 | 32G | 1T HDD | 50M/无限流量 | $196.00 | 立即申请 |
香港服务器2 | E5-2650 | 32G | 1T HDD | 50M/无限流量 | $256.00 | 立即申请 |
香港服务器3 | E5-2680 | 32G | 1T HDD | 50M/无限流量 | $316.00 | 立即申请 |
香港服务器4 | E5-2690 | 32G | 1T HDD | 50M/无限流量 | $336.00 | 立即申请 |
香港服务器5 | E5-2697 | 32G | 1T HDD | 50M/无限流量 | $376.00 | 立即申请 |
香港服务器6 | E5-2620*2 | 32G | 1T HDD | 50M/无限流量 | $376.00 | 立即申请 |
香港服务器7 | E5-2650*2 | 32G | 1T HDD | 50M/无限流量 | $436.00 | 立即申请 |
香港服务器8 | E5-2680*2 | 32G | 1T HDD | 50M/无限流量 | $476.00 | 立即申请 |
香港服务器9 | E5-2690*2 | 32G | 1T HDD | 50M/无限流量 | $556.00 | 立即申请 |
香港服务器10 | E5-2697*2 | 32G | 1T HDD | 50M/无限流量 | $596.00 | 立即申请 |
香港服务器11 | E5-2680v4*2 | 32G | 1T HDD | 50M/无限流量 | $696.00 | 立即申请 |
香港服务器12 | E5-2698v4*2 | 32G | 1T HDD | 50M/无限流量 | $796.00 | 立即申请 |
一,新建一个项目TestWeb,项目类型:Windows窗口应用程序。二,新建类RequestProcessor。using System;using System.IO;using ;using .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 + );SendStr(coding, Date: );SendStr(coding, Server: httpsrv/1.0 );SendStr(coding, MIME-Version: 1.0 );SendStr(coding, Content-Type: + fileType + );
strSend = Content-Length: + length.ToString();SendStr(coding, strSend + );
//发送一个空行SendStr(coding, );}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);elserd = 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 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 ;using .Sockets;using System.Text;using System.Threading;
namespace TestWeb{class ClientSocketThread{public TcpListener tcpl;//Notice: get from SrvMain.tcplprivate 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] { ' ', ' ' };string[] RequestLines = new string[32];
do{//use BUFFERSIZE contral the receive data size to avoid the BufferOverflow attackint 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 ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;
using System.IO;using ;using .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 80tcpl.Start();
// int ThreadID = 0;while (true){while (!tcpl.Pending()){Thread.Sleep(100);}
//启动接受线程ClientSocketThread myThreadHandler = new ClientSocketThread();myThreadHandler.tcpl = tcpl;//Notice: dont forget do thisThreadStart myThreadStart = new ThreadStart(myThreadHandler.HandleThread);Thread myWorkerThread = new Thread(myThreadStart);myWorkerThread.Start();}}catch (SocketException ){
}catch (FormatException){
}catch (Exception ){
}// Console.Read();
}}}