網站首頁 編程語言 正文
前言
使用 C#以B/S方式構建WebService服務十分簡便,即是使用Asp.net在網站中添加WebService服務并使用IIS發布。但如需要在C/S程序中發布WebService服務則沒有直接可用的類庫。因此需要使用另外的方式實現WebService服務。
一、實現思路
WebService實際是使用Http并遵循SOAP協議格式進行交互。能夠進行Http通訊即可實現WebService服務,只是沒了現成的類庫就需要自己編寫解析SOAP格式數據包和組織應答包。
二、步驟
1.使用HttpListener構建服務
代碼如下(示例):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Web;
namespace LadarManufacturabilityTooling
{
? ? public class HttpServic
? ? {
? ? ? ? public delegate byte[] OnGetResponseDataHandle(HttpListenerPostValue Sender);
? ? ? ? public event OnGetResponseDataHandle OnGetResponse;
? ? ? ? private static HttpListener httpPostRequest = new HttpListener();
? ? ? ? private static bool IsRun = true;
? ? ? ? public HttpServic(IPAddress HttpServerIP, int HttpServerPort)
? ? ? ? {
? ? ? ? ? ? httpPostRequest.Prefixes.Add("http://" + HttpServerIP.ToString() + ":" + HttpServerPort.ToString() + "/");
? ? ? ? ? ? try
? ? ? ? ? ? {?
? ? ? ? ? ? ? ? httpPostRequest.Start();
? ? ? ? ? ? }
? ? ? ? ? ? catch(Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? string Mes = ex.Message;
? ? ? ? ? ? }
? ? ? ? ? ? Thread ThrednHttpPostRequest = new Thread(new ThreadStart(httpPostRequestHandle));
? ? ? ? ? ? ThrednHttpPostRequest.Start();
? ? ? ? }
? ? ? ? private void httpPostRequestHandle()
? ? ? ? {
? ? ? ? ? ? while (IsRun)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? {?
? ? ? ? ? ? ? ? ? ? HttpListenerContext requestContext = httpPostRequest.GetContext();
? ? ? ? ? ? ? ? ? ? Thread threadsub = new Thread(new ParameterizedThreadStart((requestcontext) =>
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? HttpListenerContext request = (HttpListenerContext)requestcontext;
? ? ? ? ? ? ? ? ? ? ? ? //獲取Post請求中的參數和值幫助類 ?
? ? ? ? ? ? ? ? ? ? ? ? HttpListenerPostParaHelper httppost = new HttpListenerPostParaHelper(request);
? ? ? ? ? ? ? ? ? ? ? ? //獲取Post過來的參數和數據 ?
? ? ? ? ? ? ? ? ? ? ? ? HttpListenerPostValue lst = httppost.GetHttpListenerPostValue();
? ? ? ? ? ? ? ? ? ? ? ? byte[] buffer = null;
? ? ? ? ? ? ? ? ? ? ? ? if (lst != null)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? if(OnGetResponse != null)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? buffer = OnGetResponse(lst);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? if(buffer != null)
? ? ? ? ? ? ? ? ? ? ? ? {//Response ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? ? ? ? ? ? ? {?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.StatusCode = 200;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.Headers.Add("SOAPAction", "");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.Headers.Add("User-Agent", "gSOAP/2.8");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.ContentType = "text/xml; charset=utf-8";
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.ContentEncoding = Encoding.UTF8;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.ContentLength64 = buffer.Length;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var output = request.Response.OutputStream;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? output.Write(buffer, 0, buffer.Length);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? output.Close();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? catch(Exception ex2)
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? ? ? ? ? ? ? {?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? request.Response.Close();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? catch
? ? ? ? ? ? ? ? ? ? ? ? ? ? { }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }));
? ? ? ? ? ? ? ? ? ? threadsub.Start(requestContext);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? string Mes = ex.Message;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? public void StopHttpThread()
? ? ? ? {
? ? ? ? ? ? IsRun = false;
? ? ? ? ? ? httpPostRequest.Abort();
? ? ? ? }
? ? }
}
啟動服務后在httpPostRequestHandle()函數中編寫對監聽到的服務請求的處理。
//獲取Post過來的參數和數據 ?
HttpListenerPostValue lst = httppost.GetHttpListenerPostValue();
GetHttpListenerPostValue();函數作用為取出請求中的數據部分和請求的名稱。涉及到的類定義和代碼如下:
/// <summary> ?
? ? /// HttpListenner監聽Post請求參數值實體 ?
? ? /// </summary> ?
? ? public class HttpListenerPostValue
? ? {
? ? ? ? /// <summary> ?
? ? ? ? /// 0=> 參數 ?
? ? ? ? /// 1=> 文件 ?
? ? ? ? /// </summary> ?
? ? ? ? public int type = 0;
? ? ? ? /// <summary>
? ? ? ? /// 請求的類型名稱
? ? ? ? /// </summary>
? ? ? ? public string name;
? ? ? ? /// <summary>
? ? ? ? /// 數據字符串
? ? ? ? /// </summary>
? ? ? ? public string datas;
? ? }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.IO;
namespace LadarManufacturabilityTooling
{
? ? /// <summary> ?
? ? /// 獲取Post請求中的參數和值幫助類 ?
? ? /// </summary> ?
? ? public class HttpListenerPostParaHelper
? ? {
? ? ? ? private HttpListenerContext request;
? ? ? ? public HttpListenerPostParaHelper(HttpListenerContext request)
? ? ? ? {
? ? ? ? ? ? this.request = request;
? ? ? ? }
? ? ? ? /// <summary> ?
? ? ? ? /// 獲取Post過來的參數和數據 ?
? ? ? ? /// </summary> ?
? ? ? ? /// <returns></returns> ?
? ? ? ? public HttpListenerPostValue GetHttpListenerPostValue()
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? HttpListenerPostValue HttpListenerPostValueList = new HttpListenerPostValue();
? ? ? ? ? ? ? ? if (true)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? Stream body = request.Request.InputStream;
? ? ? ? ? ? ? ? ? ? Encoding encoding = Encoding.UTF8;
? ? ? ? ? ? ? ? ? ? StreamReader reader = new System.IO.StreamReader(body, encoding);
? ? ? ? ? ? ? ? ? ? if (request.Request.ContentType != null)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? Console.WriteLine("Client data content type {0}", request.Request.ContentType);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? string datas = reader.ReadToEnd();
? ? ? ? ? ? ? ? ? ? string Requestname = request.Request.RawUrl.Replace("/","");
? ? ? ? ? ? ? ? ? ? HttpListenerPostValueList.datas = datas;
? ? ? ? ? ? ? ? ? ? HttpListenerPostValueList.name = Requestname;
? ? ? ? ? ? ? ? ? ? Console.WriteLine(datas);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return HttpListenerPostValueList;
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
以上部分和構建普通的http監聽服務并無區別。
2.處理請求的數據
OnGetResponse事件用于處理請求的數據并組織回包
代碼如下(示例):
private byte[] ThisHttpServic_OnGetResponse(HttpListenerPostValue Sender)
? ? ? ? {
? ? ? ? ? ? byte[] buffer = null;
? ? ? ? ? ? string restr = "";
? ? ? ? ? ? //處理收到的請求
? ? ? ? ? ? switch (Sender.name)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case "MyServiceName":
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? string xmlOrgstr = "";
? ? ? ? ? ? ? ? ? ? int iStartPos = Sender.datas.IndexOf("<xmlData>", 1);
? ? ? ? ? ? ? ? ? ? int iStopPos = Sender.datas.IndexOf("</xmlData>", 1);
? ? ? ? ? ? ? ? ? ? if (iStartPos > 0)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? xmlOrgstr = Sender.datas.Substring(iStartPos + 9, iStopPos - iStartPos - 9);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? string xmlstr = HttpUtility.HtmlDecode(xmlOrgstr);
? ? ? ? ? ? ? ? ? ? string LOGIN_ACK = GetPack(xmlstr);
? ? ? ? ? ? ? ? ? ? restr = GetCompleteSoapString(System.Security.SecurityElement.Escape(LOGIN_ACK));
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? restr = "";
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? buffer = System.Text.Encoding.UTF8.GetBytes(restr);
? ? ? ? ? ? return buffer;
? ? ? ? }
需要從收到的http請求的數據部分提取出WebService服務的參數。
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:client1="http://LSCService.chinamobile.com" xmlns:service1="http://FSUService.chinamobile.com"> <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <client1:invoke> <xmlData><?xml version="1.0" encoding="UTF-8" ?><Request><PK_Type><Name>LOGIN</Name></PK_Type><Info><UserName>cmcc</UserName><PassWord>B101341CC2E4D6F5B395C7544B96A826</PassWord><FSUID>21202110060001</FSUID><FSUIP>192.168.1.253</FSUIP><FSUMAC>00:21:92:01:b5:9f</FSUMAC><FSUVER>2.0.0.15 for CMCC</FSUVER></Info></Request>
 </xmlData> </client1:invoke>< /SOAP-ENV:Body> </SOAP-ENV:Envelope>
收到的數據包原文(Sender.datas)為:
作為示例的服務的參數名為xmlData從SOAP中截取出參數的字符串進行處理。
由于xmlData中的內容是一串xml字符,SOAP傳輸時經過了轉義,因此還需要轉義回來。
string xmlstr = HttpUtility.HtmlDecode(xmlOrgstr);
處理完相應的業務,將需要回復的數據加上SOAP協議的頭尾組好回復包返回。需要轉義的部分記得進行符號轉義。
System.Security.SecurityElement.Escape(LOGIN_ACK)
SOAP協議的頭尾根據WebService服務函數的定義有所不同,需要自行組織。示例如下:
/// <summary>
/// 返回完整的SOAP包
/// </summary>
/// <param name="XmlData">應答部分</param>
/// <returns></returns>
public static string GetCompleteSoapString(string XmlData)
{
string restr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\""
+ " xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:client1=\"http://LService.mobile.com\""
+ " xmlns:service1=\"http://FService.mobile.com\">"
+ "<SOAP-ENV:Body>"
+ "<client1:invokeResponse><invokeReturn>";
string restrEnd = "</invokeReturn></client1:invokeResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>";
restr = restr + XmlData + restrEnd;
return restr;
}
總結
既然C# 并未提供在C/S程序使用的WebService服務的.Net庫,那么就使用HttpListener監聽http請求自行解出其中的輸入數據,再根據SOAP協議進行處理。以此方式實現WebService服務。
原文鏈接:https://blog.csdn.net/qq_35034209/article/details/125744586
相關推薦
- 2022-09-24 教你創建一個帶診斷工具的.NET鏡像_C#教程
- 2022-04-03 Nginx構建Tomcat集群的操作方法_nginx
- 2023-01-23 Electron打包React生成桌面應用方法詳解_React
- 2022-10-25 C++構建函數使用介紹_C 語言
- 2022-10-28 React?this.setState方法使用原理分析介紹_React
- 2022-06-07 python字符串的一些常見實用操作_python
- 2022-03-30 jupyter?notebook使用argparse傳入list參數_python
- 2023-02-12 C++?STL之string的模擬實現實例代碼_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支