Codice di esempio per client JSON-RPC in C #
Domanda
Ho bisogno di un semplice client JSON-RPC 1.0 in C #, preferibilmente utilizzando .NET 2.0 o versione successiva. Ho controllato JRock 0.9 Hanno diversi campioni tra cui lettore di Yahoo, ma i campioni demo JSON, non JSON-RPC. Capisco che potrei implementare parte di RPC utilizzando uno qualsiasi dei parser JSON disponibili, come JRock o due da Microsoft. Io preferirei un campione pronto.
Soluzione
Ci sono due implementazioni diverse. Leggi tutta la discussione + controllare gli allegati
Altri suggerimenti
I campioni di cui sopra lavoro con le richieste HTTP. Ecco una variante che funziona con il protocollo TCP (la classe Nil è solo una classe vuota utilizzata per le richieste senza valore di ritorno):
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Newtonsoft.Json.Linq;
using AustinHarris.JsonRpc;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Concurrency;
using System.Net.Sockets;
using System.Text;
namespace JsonRpc
{
public class JsonRpcClient
{
private static object idLock = new object();
private static int id = 0;
public Encoding encoding { get; set; }
public JsonRpcClient(IPEndPoint serviceEndpoint, Encoding encoding)
{
this.serviceEndPoint = serviceEndpoint;
this.encoding = encoding;
}
private static Stream CopyAndClose(Stream inputStream)
{
const int readSize = 256;
byte[] buffer = new byte[readSize];
MemoryStream ms = new MemoryStream();
int count = inputStream.Read(buffer, 0, readSize);
while (count > 0)
{
ms.Write(buffer, 0, count);
count = inputStream.Read(buffer, 0, readSize);
}
ms.Position = 0;
inputStream.Close();
return ms;
}
public IObservable<JsonResponse<T>> InvokeWithScheduler<T>(string method, object arg, IScheduler scheduler)
{
var req = new AustinHarris.JsonRpc.JsonRequest()
{
Method = method,
Params = new object[] { arg }
};
return InvokeRequestWithScheduler<T>(req, scheduler);
}
public IObservable<JsonResponse<T>> InvokeSingleArgument<T>(string method, object arg)
{
var req = new AustinHarris.JsonRpc.JsonRequest()
{
Method = method,
Params = new object[] { arg }
};
return InvokeRequest<T>(req);
}
public IObservable<JsonResponse<T>> InvokeWithScheduler<T>(string method, object[] args, IScheduler scheduler)
{
var req = new AustinHarris.JsonRpc.JsonRequest()
{
Method = method,
Params = args
};
return InvokeRequestWithScheduler<T>(req, scheduler);
}
public IObservable<JsonResponse<T>> Invoke<T>(string method, object[] args)
{
var req = new AustinHarris.JsonRpc.JsonRequest()
{
Method = method,
Params = args
};
return InvokeRequest<T>(req);
}
public IObservable<JsonResponse<T>> InvokeRequestWithScheduler<T>(JsonRequest jsonRpc, IScheduler scheduler)
{
var res = Observable.Create<JsonResponse<T>>((obs) =>
scheduler.Schedule(()=>{
makeRequest<T>(jsonRpc, obs);
}));
return res;
}
public IObservable<JsonResponse<T>> InvokeRequest<T>(JsonRequest jsonRpc)
{
return InvokeRequestWithScheduler<T>(jsonRpc, ImmediateScheduler.Instance);
}
private string sendAndReceive(string messageToSend) {
string res = null;
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try {
// Create a TCP/IP socket.
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try {
socket.Connect(this.serviceEndPoint);
Console.Write("Socket connected to "+socket.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = encoding.GetBytes(messageToSend);
// Send the data through the socket.
int bytesSent = socket.Send(msg);
// Receive the response from the remote device.
int bytesRec = socket.Receive(bytes);
res = encoding.GetString(bytes,0,bytesRec);
Console.Write("Server response = "+res);
// Release the socket.
socket.Shutdown(SocketShutdown.Both);
socket.Close();
} catch (ArgumentNullException ane) {
Console.Write("ArgumentNullException : "+ane.ToString());
} catch (SocketException se) {
Console.Write("SocketException : " + se.ToString());
} catch (Exception e) {
Console.Write("Unexpected exception : " + e.ToString());
}
} catch (Exception e) {
Console.Write(e.ToString());
}
return res;
}
private void makeRequest<T>(JsonRequest jsonRpc, IObserver<JsonResponse<T>> obs)
{
JsonResponse<T> rjson = null;
string sstream = "";
try
{
int myId;
lock (idLock)
{
myId = ++id;
}
jsonRpc.Id = myId.ToString();
}
catch (Exception ex)
{
obs.OnError(ex);
}
try
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonRpc)+"\r\n";
if (typeof(T).Equals(typeof(Nil)))
{
sendAndReceive(json);
rjson = new JsonResponse<T>();
}
else
{
sstream = sendAndReceive(json);
rjson = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonResponse<T>>(sstream);
}
}
catch (Exception ex)
{
obs.OnError(ex);
}
if (rjson == null)
{
string exceptionMessage = "";
try
{
JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(sstream) as JObject;
exceptionMessage = jo["Error"].ToString();
}
catch(Exception ex){
exceptionMessage = sstream+"\r\n"+ex.Message;
}
obs.OnError(new Exception(exceptionMessage));
}
else
{
obs.OnNext(rjson);
}
obs.OnCompleted();
}
public IPEndPoint serviceEndPoint { get; set; }
}
}
Ecco un esempio di un cliente .net4 esposto attraverso osservabili (Rx). http://jsonrpc2.codeplex.com/SourceControl/changeset/view/13061#63133
Ecco un client WP7 quasi identico che viene esposta anche attraverso Rx. http://jsonrpc2.codeplex.com/SourceControl/changeset/view/13061#282775
Entrambi questi esempi fanno il loro lavoro in modo asincrono in modo che possano essere più complicato allora si sta cercando, a meno che naturalmente si voleva esempi che erano asincrono. :)
Buona fortuna!