1、依赖环境
Newtonsoft JSON库,严重依赖
LogHelper 自写的日志记录库 只记录调试信息 可替换或不用
2、类的实现代码
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
public class RestApiServer
{
/// <summary>
/// HTTP监听服务
/// </summary>
private HttpListener server = new HttpListener();
/// <summary>
/// 声明数据接收委托
/// </summary>
/// <param name="method"></param>
/// <param name="data"></param>
public delegate void delegate_receive_data(string method, Dictionary<string, object> data);
/// <summary>
/// 声明事件
/// </summary>
public event delegate_receive_data receive_data;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="url">监听URL地址</param>
public RestApiServer(string url)
{
server.Prefixes.Add(url); //添加服务前缀
server.Start(); //开启服务
server.BeginGetContext(new AsyncCallback(GetContextCallBack), server); //接收数据 异步方式
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="ar"></param>
private void GetContextCallBack(IAsyncResult ar)
{
try
{
server = ar.AsyncState as HttpListener;
HttpListenerContext context = server.EndGetContext(ar);
server.BeginGetContext(new AsyncCallback(GetContextCallBack), server);
Dictionary<string, object> nc_get = new Dictionary<string, object>();
Dictionary<string, object> nc_post = new Dictionary<string, object>();
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
context.Response.AppendHeader("server", "SharpServer 1.0 by lzl640");//后台跨域请求,通常设置为配置文件
context.Response.StatusCode = 200;//设置返回给客服端http状态代码
JToken j_get = null; //GET传值
JToken j_post = null; //POST传值
//处理请求
switch (context.Request.HttpMethod)
{
case "POST":
HttpListenerPostParaHelper httppost = new HttpListenerPostParaHelper(context);//获取Post请求中的参数和值帮助类
List<HttpListenerPostValue> lst = httppost.GetHttpListenerPostValue();//获取Post过来的参数和数据
foreach (var item in lst)
{
string key = item.name;
string value = Encoding.UTF8.GetString(item.datas).Replace("\r\n", "");
nc_post.Add(key, value);
}
j_post = JToken.FromObject(nc_post);
break;
case "GET":
NameValueCollection nvc = HttpUtility.ParseQueryString(context.Request.Url.Query, Encoding.GetEncoding("utf-8"));
var items = nvc.AllKeys.SelectMany(nvc.GetValues, (k, v) => new { key = k, value = v });
foreach (var item in items)
{
nc_get.Add(item.key, item.value);
}
j_get = JToken.FromObject(nc_get);
break;
default:
break;
}
//回答内容
object obj = new
{
code = 0,
message = "ok",
method = context.Request.HttpMethod,
get_value = j_get,
post_value = j_post,
};
JObject jo = JObject.FromObject(obj);
string responseString = jo.ToString();
byte[] buffer_utf8 = Encoding.GetEncoding("utf-8").GetBytes(responseString);
Stream output = context.Response.OutputStream;
//context.Response.KeepAlive = false;
context.Response.ContentType = "application/json;charset=utf-8";
output.Write(buffer_utf8, 0, buffer_utf8.Length);
output.Close();
//其它处理code
switch (context.Request.HttpMethod)
{
case "GET":
if (j_get != null)
{
receive_data("GET", j_get.ToObject<Dictionary<string, object>>());
}
else
{
// receive_data("GET", null);
}
break;
case "POST":
if (j_post != null)
{
receive_data("POST", j_post.ToObject<Dictionary<string, object>>());
}
else
{
// receive_data("POST", null);
}
break;
default:
break;
}
}
catch (Exception ex)
{
LogHelper.LogApi.WriteLog($@"解码错误:{ex.Message}");
// Debug.Print($@"解码错误:{ex.Message}");
}
}
/// <summary>
/// HttpListenner监听Post请求参数值实体
/// </summary>
private class HttpListenerPostValue
{
/// <summary>
/// 0=> 参数
/// 1=> 文件
/// </summary>
public int type = 0;
public string name;
public byte[] datas;
}
/// <summary>
/// 获取Post请求中的参数和值帮助类
/// </summary>
private class HttpListenerPostParaHelper
{
private HttpListenerContext request;
public HttpListenerPostParaHelper(HttpListenerContext request)
{
this.request = request;
}
/// <summary>
/// 比较字节数组
/// </summary>
/// <param name="source"></param>
/// <param name="comparison"></param>
/// <returns></returns>
private bool CompareBytes(byte[] source, byte[] comparison)
{
try
{
int count = source.Length;
if (source.Length != comparison.Length)
return false;
for (int i = 0; i < count; i++)
if (source[i] != comparison[i])
return false;
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 流转字节
/// </summary>
/// <param name="SourceStream"></param>
/// <returns></returns>
private byte[] ReadLineAsBytes(Stream SourceStream)
{
var resultStream = new MemoryStream();
while (true)
{
int data = SourceStream.ReadByte();
resultStream.WriteByte((byte)data);
if (data == 10)
break;
}
resultStream.Position = 0;
byte[] dataBytes = new byte[resultStream.Length];
resultStream.Read(dataBytes, 0, dataBytes.Length);
return dataBytes;
}
/// <summary>
/// 获取Post过来的参数和数据
/// </summary>
/// <returns></returns>
public List<HttpListenerPostValue> GetHttpListenerPostValue()
{
try
{
List<HttpListenerPostValue> HttpListenerPostValueList = new List<HttpListenerPostValue>();
if (request.Request.ContentType.Length > 20 && string.Compare(request.Request.ContentType.Substring(0, 20), "multipart/form-data;", true) == 0) //含文件表单
{
string[] HttpListenerPostValue = request.Request.ContentType.Split(';').Skip(1).ToArray();
string boundary = string.Join(";", HttpListenerPostValue).Replace("boundary=", "").Trim();
byte[] ChunkBoundary = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
byte[] EndBoundary = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
Stream SourceStream = request.Request.InputStream;
var resultStream = new MemoryStream();
bool CanMoveNext = true;
HttpListenerPostValue data = null;
while (CanMoveNext)
{
byte[] currentChunk = ReadLineAsBytes(SourceStream);
if (!Encoding.UTF8.GetString(currentChunk).Equals("\r\n"))
resultStream.Write(currentChunk, 0, currentChunk.Length);
if (CompareBytes(ChunkBoundary, currentChunk))
{
byte[] result = new byte[resultStream.Length - ChunkBoundary.Length];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
CanMoveNext = true;
if (result.Length > 0)
data.datas = result;
data = new HttpListenerPostValue();
HttpListenerPostValueList.Add(data);
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Disposition"))
{
byte[] result = new byte[resultStream.Length - 2];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
CanMoveNext = true;
data.name = Encoding.UTF8.GetString(result).Replace("Content-Disposition: form-data; name=\"", "").Replace("\"", "").Split(';')[0];
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Type"))
{
CanMoveNext = true;
data.type = 1;
resultStream.Dispose();
resultStream = new MemoryStream();
}
else if (CompareBytes(EndBoundary, currentChunk))
{
byte[] result = new byte[resultStream.Length - EndBoundary.Length - 2];
resultStream.Position = 0;
resultStream.Read(result, 0, result.Length);
data.datas = result;
resultStream.Dispose();
CanMoveNext = false;
}
}
}
else if (request.Request.ContentType.Contains("application/x-www-form-urlencoded")) //QueryString: name_1=value_1&name_2=value_2
{
StreamReader reader = new StreamReader(request.Request.InputStream);
string msg = reader.ReadToEnd();//读取传过来的信息
NameValueCollection nc_get = HttpUtility.ParseQueryString(msg, Encoding.GetEncoding("utf-8"));
for (int i = 0; i < nc_get.Count; i++)
{
HttpListenerPostValue data = new HttpListenerPostValue();
data.name = nc_get.GetKey(i);
data.datas = Encoding.UTF8.GetBytes(nc_get.Get(i));
HttpListenerPostValueList.Add(data);
}
}
else if (request.Request.ContentType.Contains("application/json")) //JSON格式字符串 {"name_1":"value_1","name_2":"value_2"}
{
StreamReader reader = new StreamReader(request.Request.InputStream);
string msg = reader.ReadToEnd();//读取传过来的信息
Dictionary<string, object> dic = JToken.Parse(msg).ToObject<Dictionary<string, object>>();
foreach (var item in dic)
{
HttpListenerPostValue data = new HttpListenerPostValue();
data.name = item.Key.ToString();
data.datas = Encoding.UTF8.GetBytes(item.Value.ToString());
HttpListenerPostValueList.Add(data);
}
}
else if (request.Request.ContentType.Contains("text/plain")) //原始文本 value_1
{
StreamReader reader = new StreamReader(request.Request.InputStream);
string msg = reader.ReadToEnd();//读取传过来的信息
HttpListenerPostValue data = new HttpListenerPostValue();
data.name = "data";
data.datas = Encoding.UTF8.GetBytes(msg);
HttpListenerPostValueList.Add(data);
}
return HttpListenerPostValueList;
}
catch (Exception ex)
{
LogHelper.LogApi.WriteLog($@"POST接收异常:{ex.Message}");
return null;
}
}
}
}
3、简单调用
public RestApiServer rest_server;
rest_server = new RestApiServer("http://192.168.1.2:8010/server.php/");
//这个字符串前缀可任意写 只要 / 结尾就行,可以冒充 php、jsp、asp、cgi .......
rest_server.receive_data += Rest_server_receive_data;
//关联数据接收事件
4、数据接收
public static void Rest_server_receive_data(string method, Dictionary<string, object> data)
{
Show_msg($@"API服务收到数据
方法:{method}
内容:
{JToken.FromObject(data)}
");
//解码数据,配置写入数据库,如有必要、重启程序,重读配置信息
if (data.Keys.Contains("a"))
{
MessageBox.Show("参数a接收到的信息"+ data["a"].ToString());
}
}
5、运行测试
浏览器 GET请求:
POST API 发送POST请求
POST API 发送POST JSON请求
程序界面响应: