2

servicestack を使用するサーバーと、JSON と protobuf-net の両方を使用してサーバーに接続するクライアントを作成しました (そのため、サーバーが動作すると確信しています...)。ここで、CF3.5 を使用して Windows Mobile で同じクライアントを開発する必要があります。CF3.5 では servicestack がサポートされていないため、クライアントの HttpWebRequest と NewtonSoft.Json.Compact を json 部分に次のように使用しました。

クラス:

[ProtoContract]
public class ReqPing 
{
}

[ProtoContract]
public class RespPing
{
    [ProtoMember(1)]
    public string Result { get; set; }
}

関数:

ReqPing iReqPing = new ReqPing();

string json = JsonConvert.SerializeObject(iReqPing);

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://192.168.0.87:82/json/syncreply/ReqPing");
req.ContentType = "text/json";
req.Method = "POST";
req.ContentLength = json.Length;

            using (var streamWriter = new StreamWriter(req.GetRequestStream()))
            {
                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            }

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            Stream respStream = resp.GetResponseStream();

            string resps;

            using (var reader = new StreamReader(respStream, Encoding.UTF8))
            {
                resps = reader.ReadToEnd();                
            }

            respStream.Close();

            JsonTextReader jreader = new JsonTextReader(new StringReader(resps));
            JsonSerializer serializer = new JsonSerializer();
            RespPing iRespPing = serializer.Deserialize<RespPing>(jreader);

動作するので、protobufで同じことを実装しようとしていますが、ここで立ち往生しています:

ReqPing iReqPing = new ReqPing();


var ms = new MemoryStream();?????? correct way?

Serializer.Serialize<ReqPing>(ms, iReqPing);

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://192.168.0.87:82/x-protobuf/reply/ReqPing");
            req.ContentType = "application/x-protobuf";
            req.Method = "POST";
            req.ContentLength = ????????

how can I write the serialized stream to req??               

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            Stream respStream = resp.GetResponseStream();

            RespPing iRespPing = Serializer.Deserialize<RespPing>(respStream);

誰でも正しい方法を教えてもらえますか?

ありがとう!マティア

編集:

ストリームの使用方法についてはわかりましたが、ContentLength も設定する必要があります。そうしないと、GetRequestStream でエラー メッセージが表示されます (ContentLength を設定する必要があるということです...)。私はそれを動作させました:

byte[] data;
        using(var stream = new MemoryStream()) 
        {
            Serializer.Serialize(stream, iReqPing);
            data = stream.ToArray();
            req.ContentLength = data.Length;
        }

        using(var stream = req.GetRequestStream()) 
        {
            stream.Write(data, 0, data.Length);                
        }

私が見逃している別の明らかな方法はありますか?

別の質問: 私はそれを機能させましたが、2 つの要求の後、3 番目に GetRequestStream でタイムアウトします。以前の呼び出しで、HttpWebResponse で Close() を呼び出すのを忘れていたことに気付きました。修正したところ、動作するようになりました。奇妙なことに、JSON バージョンでも HttpWebResponse を閉じるのを忘れていましたが、問題はありませんでした...ルーチンはまったく同じです..理由を推測できますか? 再度、感謝します!

4

1 に答える 1

1

シリアル化されたストリームを req に書き込むにはどうすればよいですか??

using(var stream = req.GetRequestStream()) {
    Serializer.Serialize(stream, iReqPing);
}

そして、すでに正しく持っているように、デシリアライズします:

RespPing iRespPing;
using(var stream = resp.GetResponseStream()) {
    iRespPing = Serializer.Deserialize<RespPing>(respStream);
}

MemoryStream特に長さを手動で送信したい場合を除き、a は必要ありません。バッファリングしたい場合は、次のようにします。

byte[] data;
using(var stream = new MemoryStream()) {
    Serializer.Serialize(stream, iReqPing);
    data = stream.ToArray();
}
...
using(var stream = req.GetRequestStream()) {
    stream.Write(data, 0, data.Length);
}

MemoryStream編集して、現在編集されている質問をより効率的に使用できるようにします。

    byte[] data;
    int len;
    using(var stream = new MemoryStream()) 
    {
        Serializer.Serialize(stream, iReqPing);
        data = stream.GetBuffer(); // note this is oversized!
        len = (int)stream.Length;
    }
    req.ContentLength = len;

    using(var stream = req.GetRequestStream()) 
    {
        stream.Write(data, 0, len); 
    }

ここでの微妙な点は、MemoryStreamのバッファーを複製する必要がなくなったことです。代わりに、特大サイズのバックバッファーを取得し (実際にどれくらいの量がデータであるかに注意してください)、その数のバイトだけを書き込みます。data.Length(例として)そうかもしれません4096が、そうかもlenしれません3012。これにより、余分なbyte[]割り当てとBuffer.BlockCopy.

于 2013-04-25T06:29:24.273 に答える