Я пытаюсь отправить запросы к API, который использует JSON-RPC. Я тестировал сервер с 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 не отправляет сообщения с заголовками 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();
}
@jdweng, насколько я понимаю, можно установить постоянное соединение через веб-сокет, если да, будет ли каждый отправленный запрос иметь соответствующие заголовки? Или только начальное рукопожатие для установки веб-сокета? Ожидают ли веб-API по умолчанию, что сообщения будут получены с заголовками HTTP по умолчанию?
TCP-соединение остается открытым между запросами. Каждое HTTP-сообщение имеет заголовок, но исходный заголовок может иметь больше параметров, чем последующие сообщения. См. Wiki: Веб-API en.wikipedia.org/wiki/Hypertext_Transfer_Protocol могут использовать любой IP-протокол. Я думаю, что в этом случае Web относится к любому IP-протоколу, а не только к HTTP. Большинство веб-API используют http. Но некоторые из них - это SMTP (электронная почта) и FTP (передача файлов), которые являются расширенными формами http. У вас может быть TELNET API, который представляет собой простые приложения чата TCP.
TCP - это транспортный уровень для HTTP. TCP отправляет только необработанные данные, и вы должны добавить любые заголовки http. Сетевой веб-сокет добавит заголовки по умолчанию. Вы можете многому научиться, используя сниффер, такой как wirehark, который выдаст вам все отправляемые IP-сообщения.