c# - JSON-RPC API 的 C# 客户端
问题描述
我正在尝试向与 JSON-RPC 对话的 API 发送请求。我已经使用 Curl 测试了服务器,如下所示:
> curl -v -d 'SOME_INVALID_REQUEST' http://erbium1.sytes.net:50001
{"jsonrpc": "2.0", "error": {"code": -32700, "message": "invalid JSON"}, "id": null}
我感兴趣的一些请求是订阅,因此发送 POST 请求似乎不适合这样做,因为我不希望服务器立即回复,而是接收一个或多个通知。
我正在尝试使用 C# 与该服务器通信,但该服务器从不回复。要发送消息,我已完成以下操作:
- 创建了一个TcpClient
- 将客户端连接到服务器(erbium1.sytes.net,50001)
- 从连接的客户端转到NetworkStream
- 写入 NetworkStream 当我将这些消息发送到服务器时,读取回调函数永远不会被调用,因此我永远不会收到来自服务器的回复。如果我要将消息发送到端口 50002 (TLS) 而不是 50001,则服务器会回复一个空字符串。
我的猜测是,进行原始 TcpClient 连接不会发送带有 HTTP 标头的消息,因此服务器只是丢弃它们?如果是这样,什么是请求订阅服务器并能够接收通知的合适方式?
TcpClient 连接和 WebSocket 之间有什么区别?WebSocket 是否适合在这里使用?
下面是我的代码示例:
// State object for receiving data from remote device.
public class ReceiverState {
public ReceiverState(NetworkStream s) {
this.stream = s;
}
public NetworkStream stream;
public const int bufferSize = 1024;
public byte[] buffer = new byte[bufferSize];
public AutoResetEvent receivedEvent = new AutoResetEvent(false);
}
static AutoResetEvent received = new AutoResetEvent(false);
public static void PingServer(NetworkStream stream) {
if (stream.CanWrite) {
try {
String rpc = "INVALID_REQUEST";
Byte[] data = System.Text.Encoding.UTF8.GetBytes(rpc);
stream.Write(data, 0, data.Length);
stream.Flush();
Console.WriteLine("Pinging...");
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
} else {
// TODO Throw an exception
Console.WriteLine("Unable to write to stream");
}
}
public static void BeginAsyncRead(NetworkStream stream, ReceiverState readState) {
if (stream.CanRead) {
try {
stream.BeginRead(readState.buffer, 0, 1024,
new AsyncCallback(readCallBack),
readState);
}
catch (Exception e) {
Console.WriteLine(e.ToString());
}
} else {
// TODO Throw an exception
Console.WriteLine("Unable to read from stream");
}
}
private static void readCallBack(System.IAsyncResult ar) {
// Get the state from AsyncResult
ReceiverState state = (ReceiverState) ar.AsyncState;
if(ar.IsCompleted){
Int32 numBytes = state.stream.EndRead(ar);
Console.WriteLine("Received : ");
Console.WriteLine(Encoding.ASCII.GetString(state.buffer,0,numBytes+10));
state.receivedEvent.Set();
}
}
private static void synchronousRead(NetworkStream myNetworkStream) {
if(myNetworkStream.CanRead){
byte[] myReadBuffer = new byte[1024];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
do{
numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
}
while(myNetworkStream.DataAvailable);
// Print out the received message to the console.
Console.WriteLine("You received the following message : " +
myCompleteMessage);
}
else{
Console.WriteLine("Sorry. You cannot read from this NetworkStream.");
}
}
public static void Main(string[] args) {
// Create a new TcpClient
TcpClient client = new TcpClient();
Console.WriteLine("Connecting...");
client.Connect("electrum3.hachre.de", 50001);
NetworkStream stream = client.GetStream();
Stream inStream = new MemoryStream();
ReceiverState readState = new ReceiverState(stream);
readState.receivedEvent = received;
BeginAsyncRead(stream, readState);
PingServer(stream);
received.WaitOne();
}
解决方案
推荐阅读
- file - 打开大型 NFO 文件
- flutter - 使用 StreamBuilder 代替 FeatureBuilder 来避免 Firestore 中的 whereIn 10 限制
- node.js - Express session regenerate回调被多次调用
- javascript - 在js中的字符串之间添加空格
- php - 在运行相同代码的两台不同服务器上收到不同的 GoogleAuthenticator 代码
- c# - 如何使我的 C# 应用程序使用其 SQLite 数据库的副本实际部署?
- android - 如何使用 Exoplayer 播放从 Mediastore 获取的视频
- reactjs - 当 Firestore 已经在 Next.js 应用程序中运行时,它会继续尝试设置模拟器
- python - Pyautogui 无法正常工作!帮我
- pytorch - pytorch 预测崩溃会话中的 DeepAR 实例化