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 = ;
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的基本使用差不多如此。
最重要的是对消息的处理
Socket 简易静态服务器 WPF MVVM模式(四)的更多相关文章
- Socket 简易静态服务器 WPF MVVM模式(一)
整体代码下载 主要实现功能: Socket的简单应用 可修改IP和端口 显示来访信息 界面设计: 界面采用MVVM设计,很简陋. 前台的主要目的是 输入IP地址 输入端口 输入文件目录 开启监听和停止 ...
- Socket 简易静态服务器 WPF MVVM模式(三)
ViewModels类 这个类其实就是个大杂烩,什么都可以用 这个类没有什么东西,最多的就是写一下xaml页面的逻辑控制,开启关闭监听 using System; using System.Colle ...
- Socket 简易静态服务器 WPF MVVM模式(二)
command类 标准来说,command会有三种模式,委托命令 准备命令 附加命令 1.DelegateCommand 2.RelayCommand 3.AttachbehaviorCommand ...
- WPF MVVM模式的一些理解
/*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- wpf mvvm模式下CommandParameter传递多参
原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- WPF MVVM模式下的无阻塞刷新探讨
很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...
- WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...
随机推荐
- python使用pika链接rabbitmq Connection reset by peer 解决办法
记录一下, 最近在用机器学习打算做一个Rest API, 数据存入mongo,任务采用消息队列,rabbitmq 由于引擎采用python编写,所以WEB也直接打算用python编写了,比较省事. W ...
- leetcode804
int uniqueMorseRepresentations(vector<string>& words) { map<char, string> st; st.ins ...
- ocx控件针对网页刷新和关闭分别进行区分处理
当ocx加载在网页上时,如果对网页执行F5刷新事件,ocx控件会销毁ocx的窗口类,但是ocx的APP类是不会销毁的. 只有当网页被关闭时,才销毁app类. --------------------- ...
- ssh免密连接远程服务器
ssh免密连接远程服务器 借助ssky-keygen和ssh-copy-id工具,通过4个简单的步骤实现无需输入密码登录远程Linux主机 1 生成密钥 通过内置的工具生成RSA算法加密的密钥 ssh ...
- 通过模板判断Value是否为指针
有个参数,需要判断其Value是否为指针,如果是做相应的处理. 代码示例如下,后来发现is_pointer在std空间中. #include <stdio.h> #include<i ...
- Spring总结四:IOC和DI 注解方式
首先我们要了解注解和xml配置的区别: 作用一样,但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置,也就是说我们使用了注解的方式,就不用再xml里面进行配置了,相对来说注解方式 ...
- 【bzoj3942】[Usaco2015 Feb]Censoring
[题目大意] 有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程. [样例输入] whatth ...
- mfs监控
web gui 监控 gui_info.jpg (143.72 KB, 下载次数: 83) gui_most.jpg (209.36 KB, 下载次数: 82) gui_master_info.jpg ...
- Shiro的 rememberMe 功能使用指导(为什么rememberMe设置了没作用?)
UsernamePasswordToken token = new UsernamePasswordToken(loginForm.getUsername(),loginForm.getPasswor ...
- 246. Strobogrammatic Number 上下对称的数字
[抄题]: A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at u ...