
最重要的一个类Socket类
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace 简易静态服务器.Code
{
public class Server
{
public string GetStockString { get; private set; }
private bool runing = false;
private Socket ServerSocket;
private int timeout = ;
private string fileurl;
private Encoding DataToString = Encoding.UTF8;
private string RequestedFile = string.Empty;
public bool Start(IPAddress Ip,int prot,int Count,string fileurl)
{
if (runing) return false; try
{
ServerSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//监听类型
ServerSocket.Bind(new IPEndPoint(Ip,prot));
ServerSocket.Listen(Count);//监听实例的数量
ServerSocket.ReceiveTimeout = timeout;//超时
ServerSocket.SendTimeout = timeout;//超时
runing = true;
this.fileurl = fileurl;
}
catch { return false; } Thread requestListenerThread = new Thread(() =>{ //多线程进行处理 while (runing) //设置一直开启
{
Socket clientSocket;
try
{
clientSocket = ServerSocket.Accept();//等待接收数据 是方法内部的线程堵塞 var Handler = new Thread(() => {
clientSocket.ReceiveTimeout = timeout;
clientSocket.SendTimeout = timeout;
try
{
GetData(clientSocket);
}
catch
{
try { clientSocket.Close(); } catch { }
} });
Handler.Start(); }
catch
{ }
}
});
requestListenerThread.Start();
return true;
}
public void Stop()
{
if(runing)
{
runing = false;
try
{
ServerSocket.Close();
}
catch { }
ServerSocket.Dispose();
ServerSocket = null;
}
}
private void GetData(Socket dataSocket)
{
var bytedata = new byte[];//10KB的接受消息量 int dataCount = dataSocket.Receive(bytedata);//转换消息 string strReceived = DataToString.GetString(bytedata, , dataCount);//转换字节到string GetStockString = strReceived; OnStocketStringChange?.Invoke(strReceived);//事件传递参数到viewmodel string httpmethod = strReceived.Substring(, strReceived.IndexOf(" "));//获取第一个空格到起始位置之间所有的字符 int StartMethodUrl = strReceived.IndexOf(httpmethod) + httpmethod.Length + ;//获取请求内容的起始位置。也是直接写作httpmethod.length+1 int EndMethodUrl = strReceived.Substring(, strReceived.IndexOf("\r\n")).IndexOf("HTTP") - StartMethodUrl; //strReceived.LastIndexOf("HTTP") - StartMethodUrl - 1; string MethodUrl = strReceived.Substring(StartMethodUrl, EndMethodUrl);//获取请求内容 switch(httpmethod)
{
case "GET":
case "POST":
RequestedFile = MethodUrl;
break;
default:
dataSocket.Close();//此处也可以是 NotImplemented(dataSocket);
return;
} RequestedFile = RequestedFile.Replace("/", "\\").Replace("\\..", "");//替换斜杠
RequestedFile = RequestedFile.Split('?')[];//分割字符串 也可以是RequestedFile.Split('?').Length>1?RequestedFile.Split('?')[0]:RequestedFile;
int TypeNameStart =RequestedFile.LastIndexOf(".") + ; int TypeNameLength = ; string Extension = "."; switch(TypeNameStart>)
{
case true:
TypeNameLength = RequestedFile.Length - TypeNameStart;
Extension += RequestedFile.Substring(TypeNameStart, TypeNameLength).Replace(" ","");//获取请求格式的字符串 switch (MimeType.Type.ContainsKey(Extension))//判断是否存在这个类型
{
case true:
switch(File.Exists(fileurl+RequestedFile))
{
case true:
SendOKResponse(dataSocket,File.ReadAllBytes(fileurl + RequestedFile), MimeType.Type[Extension]);
break;
case false:
NotFound(dataSocket);
break;
}
break;
case false:
//不存在的话 那是否直接存在这个文件?
if (File.Exists(fileurl + RequestedFile))//存在输出
SendOKResponse(dataSocket, File.ReadAllBytes(fileurl + RequestedFile), "text/html");
else//不存在 501
NotImplemented(dataSocket);
break;
}
break;
case false:
SendOKResponse(dataSocket, File.ReadAllBytes(fileurl + "\\Index.html"), "text/html"); //直接输出index页面
break;
} }
private void NotFound(Socket clientSocket)
{
SendResponse(clientSocket, "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><h2>Atasoy Simple Web Server</h2><div>404 - Not Found</div></body></html>", "404 Not Found", "text/html");
}
private void NotImplemented(Socket clientSocket)
{
SendResponse(clientSocket, "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><h2>Atasoy Simple Web Server</h2><div>501 - Method Not Implemented</div></body></html>", "501 Not Implemented", "text/html");
}
private void SendResponse(Socket clientSocket, string strContent, string responseCode, string contentType)
{
byte[] bContent = DataToString.GetBytes(strContent);
SendResponse(clientSocket, bContent, responseCode, contentType);
}
private void SendOKResponse(Socket Send, byte[] SendContent, string SendContentType) =>SendResponse(Send,SendContent,简易静态服务器.Models.SendContentType.GetSendString(Models.SendType.Send200OK),SendContentType);
private void SendResponse(Socket Send, byte[] SendContent, string SendCode, string SendContentType)
{
try
{
//处理头部
var header=DataToString.GetBytes("HTTP/1.1 " + SendCode + "\r\n"
+ "Server: Atasoy Simple Web Server\r\n"
+ "Content-Length: " +SendContent.Length.ToString() + "\r\n"
+ "Connection: close\r\n"
+ "Content-Type: " + SendContentType + "\r\n\r\n"); var AllDataByte = new byte[SendContent.Length + header.Length];//复制两个数组 Buffer.BlockCopy(header, , AllDataByte, , header.Length); Buffer.BlockCopy(SendContent, , AllDataByte, header.Length, SendContent.Length); Send.Send(AllDataByte);//发送 Send.Close();
}
catch
{ }
} public delegate void StocketStringChange(string sender);//委托
public event StocketStringChange OnStocketStringChange;//事件 }
}
基本的模式就是
开始监听
利用两个线程来处理信息
因为socket的accept自带线程堵塞,不会造成线程的大量拥堵。
此外还可以异步进行消息接受,发送
对于socket的基本使用差不多如此。
最重要的是对消息的处理