primo luogo, vorrei ringraziare calorosamente Charles Cook per il suo aiuto su questo problema e per lo sviluppo di XMLRPC. NETTO.
In secondo luogo, questo campione si basa sul campione XMLRPC.NET StateNameServer disponibile per il download qui: http://xml-rpc.net/download.html
Quindi, ecco la soluzione:
1. Generare o ottenere un [autofirmato] certificato (usando Makecert.exe per esempio)
2. Aggiungi questo certificato per la configurazione del server e specificare la porta che si desidera utilizzare con il server XMLRPC.NET (in questo caso 5678) utilizzando httpcf g.exe o un altro strumento simile HttpSysConfig (Open Source)
3. Implementare il server XMLRPC.NET utilizzando il seguente codice:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using CookComputing.XmlRpc;
using System.Net;
using System.IO;
public class _
{
static void Main(string[] args)
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("https://127.0.0.1:5678/");
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
ListenerService svc = new StateNameService();
svc.ProcessRequest(context);
}
Console.WriteLine("Press <ENTER> to shutdown");
Console.ReadLine();
}
}
public class StateNameService : ListenerService
{
[XmlRpcMethod("examples.getStateName")]
public string GetStateName(int stateNumber)
{
if (stateNumber < 1 || stateNumber > m_stateNames.Length)
throw new XmlRpcFaultException(1, "Invalid state number");
return m_stateNames[stateNumber - 1];
}
string[] m_stateNames
= { "Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylviania", "Rhose Island", "South Carolina",
"South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia",
"Washington", "West Virginia", "Wisconsin", "Wyoming" };
}
public abstract class ListenerService : XmlRpcHttpServerProtocol
{
public virtual void ProcessRequest(HttpListenerContext RequestContext)
{
try
{
IHttpRequest req = new ListenerRequest(RequestContext.Request);
IHttpResponse resp = new ListenerResponse(RequestContext.Response);
HandleHttpRequest(req, resp);
RequestContext.Response.OutputStream.Close();
}
catch (Exception ex)
{
// "Internal server error"
RequestContext.Response.StatusCode = 500;
RequestContext.Response.StatusDescription = ex.Message;
}
}
}
public class ListenerRequest : CookComputing.XmlRpc.IHttpRequest
{
public ListenerRequest(HttpListenerRequest request)
{
this.request = request;
}
public Stream InputStream
{
get { return request.InputStream; }
}
public string HttpMethod
{
get { return request.HttpMethod; }
}
private HttpListenerRequest request;
}
public class ListenerResponse : CookComputing.XmlRpc.IHttpResponse
{
public ListenerResponse(HttpListenerResponse response)
{
this.response = response;
}
string IHttpResponse.ContentType
{
get { return response.ContentType; }
set { response.ContentType = value; }
}
TextWriter IHttpResponse.Output
{
get { return new StreamWriter(response.OutputStream); }
}
Stream IHttpResponse.OutputStream
{
get { return response.OutputStream; }
}
int IHttpResponse.StatusCode
{
get { return response.StatusCode; }
set { response.StatusCode = value; }
}
string IHttpResponse.StatusDescription
{
get { return response.StatusDescription; }
set { response.StatusDescription = value; }
}
private HttpListenerResponse response;
}
public class StateNameServer : MarshalByRefObject, IStateName
{
public string GetStateName(int stateNumber)
{
if (stateNumber < 1 || stateNumber > m_stateNames.Length)
throw new XmlRpcFaultException(1, "Invalid state number");
return m_stateNames[stateNumber-1];
}
public string GetStateNames(StateStructRequest request)
{
if (request.state1 < 1 || request.state1 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
if (request.state2 < 1 || request.state2 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
if (request.state3 < 1 || request.state3 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
string ret = m_stateNames[request.state1-1] + " "
+ m_stateNames[request.state2-1] + " "
+ m_stateNames[request.state3-1];
return ret;
}
string[] m_stateNames
= { "Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylviania", "Rhose Island", "South Carolina",
"South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia",
"Washington", "West Virginia", "Wisconsin", "Wyoming" };
}
4. Implementare il client di XMLRPC.NET utilizzando il seguente codice (il codice crea anche un nuovo certificato client X509)
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using CookComputing.XmlRpc;
using System.Net;
using System.Security.Cryptography.X509Certificates;
class _
{
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy() { }
public bool CheckValidationResult(ServicePoint sp,
X509Certificate cert,
WebRequest req,
int problem)
{
return true;
}
}
static void Main(string[] args)
{
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
IStateName proxy = XmlRpcProxyGen.Create<IStateName>();
XmlRpcClientProtocol cp = (XmlRpcClientProtocol)proxy;
cp.Url = "https://127.0.0.1:5678/";
cp.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(@"C:\path\to\your\certificate\file\my.cer"));
cp.KeepAlive = false;
//cp.Expect100Continue = false;
//cp.NonStandard = XmlRpcNonStandard.All;
string stateName = ((IStateName)cp).GetStateName(13);
}
}
Certo, non me ne frega qui l'interfaccia implem entazione per ServerStateName ma lo troverai nei file di esempio usando il link di download in alto.
Nota:
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy()
; consentirà all'implementazione del server di accettare il certificato autofirmato da te generato. Penso che questo non sia necessario con i certificati emessi dalle autorità di certificazione.
Se trovi qualcosa che potrebbe essere migliorato e non è corretto, sarà molto apprezzato.
Dopo il test, posso confermare che l'implementazione funziona su due macchine Windows separate. – virrea