データの取り扱いが簡単になるPacketクラス

使用するメリット

データの終端など意識することなく読み書きが可能

デメリット

少ないデータのやり取りでは逆にデータ量が増える

public enum PacketType {
  BINARY,
  META,
  KEEP
}

public class Packet {
  public Packet(PacketType type, byte[] data)
        {
            this.Type = type;
            this.Data = data;
        }

        public PacketType Type { get; protected set; }
        public byte[] Data { get; protected set; }

        public int BinarySize
        {
            get
            {
                return Data.Length;
            }
        }
}

public class PacketWriter {
  public PacketWriter(Stream stream) {
    this.stream = stream;
  }
  private Stream stream;
  public Packet Read() {
    byte[] sof = new byte[4];
    int ty;
    byte[] buffer;
    stream.Read(sof, 0, sof.Length);
    ty = stream.ReadByte();
    int size = BitConverter.ToInt32(sof, 0);
    buffer = new byte[size];
    stream.Read(buffer, 0, size);
    PacketType type = (PacketType) ty;
    return new Packet(type, buffer);
  }
  public void Write(Packet packet) {
    int size = packet.Data.Length;
    byte[] sof = BitConverter.GetBytes(size);
    byte type = (byte) packet.Type;
    stream.Write(sof, 0, sof.Length);
    stream.WriteByte(type);
    stream.Write(packet.Data, 0, size);
  }
}

NetworkStream でOverflowExceptionが発生する

タイトルの通りなのですが、NetworkStreamを使用してデータのやり取りをしているときにOverflowExceptionが発生することが多かったのでその解決策をまとめておきます。

前提条件

  • データを送る際に Packetクラスを使用してラッパしている
  • PacketWriter を使用して読み書きを行う

 

発生原因

完璧に調べているわけではないですが、

Packetクラスでラップしているため実際のデータより少しデータが多くなることと、

読み書きの速さがとてつもなく早いことが原因だと判明しました。

解決方法

ずばりもっとも簡単な解決方法は帯域を制限することです。

具体的には Packetをラップして送るたびに カウンタの値を1増やし、

カウンタの値がXで割れるときに待機処理させるだけです。

int count = 0;

while(条件) {
  // データの送信処理
  count++;
  if (count % 10 == 0) {
    // 10回毎に 1ms 待機する
    Thread.Sleep(1);
  }
}

 

C#でイベント機能を実装する方法

いままではActionなどを使用してコールバックを作成していたのですが、

イベントを活用することでできることのはばが広がったのでやり方を紹介します。

やり方

やり方はとても簡単で、

delegate でハンドル(?)を作って変数として event を追加するだけ()

// ハンドル
public delegate void MyEventHandler<T>(object sender, T args);
// イベント用
public event MyEventHandler<object, string> DebugEventHandler;

イベントの呼び出しは Invoke を利用してもいいですし、関数のように呼び出すこともできますが、起動直後はNULLのことがあるのでNULLチェックはした方がいいです。

DebugEventHandler?.Invoke(sender, string);
DebugEventHandler(sender, string);