Socket 简易静态服务器 WPF MVVM模式(四)

最重要的一个类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 = 10;
        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[10240];//10KB的接受消息量

            int dataCount = dataSocket.Receive(bytedata);//转换消息

            string strReceived = DataToString.GetString(bytedata, 0, dataCount);//转换字节到string

            GetStockString = strReceived;

            OnStocketStringChange?.Invoke(strReceived);//事件传递参数到viewmodel
          
            string httpmethod = strReceived.Substring(0, strReceived.IndexOf(" "));//获取第一个空格到起始位置之间所有的字符

            int StartMethodUrl = strReceived.IndexOf(httpmethod) + httpmethod.Length + 1;//获取请求内容的起始位置。也是直接写作httpmethod.length+1

            int EndMethodUrl = strReceived.Substring(0, 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('?')[0];//分割字符串 也可以是RequestedFile.Split('?').Length>1?RequestedFile.Split('?')[0]:RequestedFile;
            int TypeNameStart =RequestedFile.LastIndexOf(".") + 1;

            int TypeNameLength = 0;

            string Extension = ".";


           switch(TypeNameStart>0)
            {
                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, 0, AllDataByte, 0, header.Length);

                Buffer.BlockCopy(SendContent, 0, AllDataByte, header.Length, SendContent.Length);

               

                Send.Send(AllDataByte);//发送
              
                Send.Close();
            }
            catch
            {

            }
        }

        public  delegate void StocketStringChange(string sender);//委托
        public event StocketStringChange OnStocketStringChange;//事件
        

    }
}

基本的模式就是

开始监听

利用两个线程来处理信息

因为socket的accept自带线程堵塞,不会造成线程的大量拥堵。

此外还可以异步进行消息接受,发送

对于socket的基本使用差不多如此。

最重要的是对消息的处理

 

posted @ 2018-11-09 11:00  ARM830  阅读(535)  评论(0编辑  收藏  举报