1

TCP 経由でハードウェアからデータを受信する単純なアプリケーションを開発しています。TCP データを受信するプログラムの開発方法をインターネットで少し検索しましたが、満足できるものは見つかりませんでした。これは、C# で TCP を操作する方法の非常に単純な説明か、高度なフレームワークの説明です。

プログラムの通信部分を適切なオブジェクト指向の方法で編成する方法の簡単なベスト プラクティスが必要です。助言がありますか?

理想的には、TCP 経由で送信されるさまざまな構造が、プログラム内の対応する構造体に格納されることを望みます

送信されるものの構造:

Head
{
  Int16    Mode;
  Time     Start_time //(Unix time)
  Int16    Number of records
}
for each record if mode == 1
  char[20]    Name_of_record
for each record
  float    Value_of_record //(hardware-specific float)
  Int16    Flag_of_record
Foot
{
  Time     Stop_time //(Unix time)
}

これは 1 分に 1 回送信されます。オーバーヘッドはありません。すべての変数の値を送信するだけで、それ以上は送信しません

編集 サーバーを制御することはできません。

4

2 に答える 2

2

非同期通信を使用して TCP メッセージを受信できます。

サーバー ソケットを初期化して接続を試みます。

// Specify the size according to your need.
private byte[] bytData = new byte[1024 * 50000];
private Socket oServerSocket;

private void WindowLoaded(object sender, RoutedEventArgs e)
{
    try
    {
        // We are using TCP sockets
        this.oServerSocket = new Socket(
        addressFamily: AddressFamily.InterNetwork,
        socketType: SocketType.Stream,
        protocolType: ProtocolType.Tcp);

        // Assign the any IP of the hardware and listen on port number which the hardware is sending(here it's 5656)
        var oIPEndPoint = new IPEndPoint(address: IPAddress.Any, port: 5656);

        // Bind and listen on the given address
        this.oServerSocket.Bind(localEP: oIPEndPoint);
        this.oServerSocket.Listen(backlog: 4);

        // Accept the incoming clients
        this.oServerSocket.BeginAccept(this.OnAccept, null);
        this.oLogger.WriteLog("Server started");
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
}

接続に成功した場合:

private void OnAccept(IAsyncResult ar)
{
    try
    {
        var oClientSocket = this.oServerSocket.EndAccept(asyncResult: ar);

        // Start listening for more clients
        this.oServerSocket.BeginAccept(callback: this.OnAccept, state: null);

        // Once the client connects then start receiving the commands from her
        oClientSocket.BeginReceive(
        buffer: this.bytData,
        offset: 0,
        size: this.bytData.Length,
        socketFlags: SocketFlags.None,
        callback: this.OnReceive,
        state: oClientSocket);
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
}

受信したメッセージを処理します。

private void OnReceive(IAsyncResult ar)
{
    try
    {
        var oClientSocket = (Socket)ar.AsyncState;
        oClientSocket.EndReceive(asyncResult: ar);

        /* Process the data here

        BitConverter.ToInt32(value: this.bytData, startIndex: 0);
        string SomeString= Encoding.ASCII.GetString(bytes: this.bytData, index: 8, count: 5);

        */

        // Specify the size according to your need.
        this.bytData = null;
        this.bytData = new byte[1024 * 50000];
        oClientSocket.BeginReceive(
            buffer: this.bytData,
            offset: 0,
            size: this.bytData.Length,
            socketFlags: SocketFlags.None,
            callback: this.OnReceive,
            state: oClientSocket);
    }

    catch (Exception ex)
    {
        // Handle Exception
    }
}
于 2012-08-25T12:45:03.553 に答える
1

通常、手順は同じです。

1)tcpストリームからデータを読み取り、それをバッファー(通常はバイト配列)に格納します。

2)バッファを継続的にチェックして(更新するたびに)、完全なパケットが到着したかどうかを判断します。

3)バッファを解析し、パケットを目的のOOオブジェクトに抽出します

4)オブジェクトをキューに追加してさらに処理するか、バックグラウンドスレッドを呼び出してパケットオブジェクトを消費します。

出力ストリームを介してデータを送信することは、逆の順序でほとんど同じです。

バッファを扱うとき、物事は複雑/騒々しい/苦痛になる可能性があります。パケットがいつ終了し、別のパケットが開始するかを判断するには、バイナリデータを処理する必要があります。もちろん、これは、固定長のパケットや開始/停止バイトなどを送信する場合、通信しているデバイスのプロトコルに関連しています...この時点では、作成するコードは依存するため、標準的な解決策はありません。デバイスによって送信されたデータ。

編集:サンプルコードで質問を更新しましたが、重要なレコードの構造ではありません。その部分は単純で冗長に記述できます(構造体にintフィールドがある場合は、バッファーから4バイトを読み取り、そのフィールドに次のように書き込みます。BitConverterたとえば、バイトをintに変換するクラス)。ハードウェアのマニュアルを読んで、データを送信する形式(ここでも、開始/停止バイト、固定長など)を確認する必要があります。

これはそれぞれの場合に固有であり、「解決策」がないため、非常に抽象的です。また、ストリーム/ tcp接続/バイナリパケットがどのように機能するかを理解していないようです。これがtcp接続の問題であると思わせる理由は、そうではありません。TCP接続は、ネットワークを介して送信される単なるバイトストリームであり、同じパターンを使用して、ディスク上のファイルまたはシリアルポートからバイナリデータを読み取ることができます。

于 2012-08-25T11:18:20.343 に答える