C#中C/S端实现WebService服务

C#中C/S端实现WebService服务

目录

前言

一、实现思路

二、步骤

1.使用HttpListener构建服务

2.处理请求的数据

总结

前言

使用 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>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;&lt;Request&gt;&lt;PK_Type&gt;&lt;Name&gt;LOGIN&lt;/Name&gt;&lt;/PK_Type&gt;&lt;Info&gt;&lt;UserName&gt;cmcc&lt;/UserName&gt;&lt;PassWord&gt;B101341CC2E4D6F5B395C7544B96A826&lt;/PassWord&gt;&lt;FSUID&gt;21202110060001&lt;/FSUID&gt;&lt;FSUIP&gt;192.168.1.253&lt;/FSUIP&gt;&lt;FSUMAC&gt;00:21:92:01:b5:9f&lt;/FSUMAC&gt;&lt;FSUVER&gt;2.0.0.15 for CMCC&lt;/FSUVER&gt;&lt;/Info&gt;&lt;/Request&gt;&#xD;&#xA; </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服务。

到此这篇关于C#中C/S端实现WebService服务的文章就介绍到这了,更多相关C# C/S端 WebService 内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    params 是什么意思,c#里

    params 是什么意思,c#里,参数,数组,本文目录params 是什么意思,c#里params.add跟params.put有区别吗C#中ref,out和params有什么区别发送请

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session,令牌,客户端,最近在研发一款O2O产品,考虑到分布式架构的需要,以前那一套.NET的

    c#中 (ToolStrip

    c#中 (ToolStrip,窗体,控件,本文目录c#中 (ToolStrip)控件是做什么用的winform窗体问题 toolstrip怎么重用,每个窗体都要用到同样的工具栏窗体

    C#取得DataTable最大值、最小值

    C#取得DataTable最大值、最小值,最大值,最小值,C#取得DataTable最大值、最小值int max=int.Parse((dtItemsAll.Compute("Max(CPITEMS_SOR

    C#如何打印|cctv5体育节目表

    C#如何打印|cctv5体育节目表,,C#如何打印最省事的办法,引用word对象,再把word弹出来用word打印,比较适合你这样刚学的,还不容易出错。cctv5体

    C#中的listview控件怎么用

    C#中的listview控件怎么用,控件,第一个,C#中的listview控件怎么用比如你在窗体上放了一个ListView,教你一些简单的操作。listView1.Columns