|ハイブリッドOS|File System|ARM|Android|Java|制御システム|オープンシステム

 

VC

 
フォーム
 
TCP/IP通信
2014-12-23
 今回は、TCP/IP通信の簡単な Server/Client を作成してみました。
 
 < サンプルの概要 >
 今回は、ServerとClientで2つアプリケーションを作成します
 SampleTcpServer:Server側アプリケーション
 SampleTcpClient:Client側アプリケーション
 IPAddressは、localhost を指定し、1PC内で ループして使用できるようにしました。
 PortNoは 7777 としました。
 Clinetが"CMD1"を送信すると、Server側は、textBox1 に "CMD1"を表示し "Ack"を送信し
 TCP/IPの接続を閉じます。
 Client側は、"Ack"を受信したらそれを、textBox1 に表示して、TCP/IPの接続を閉じます。
 Server側は、普通、また 受信待ちなどにすると思いますが、今回は
 通信方法をメインに簡略化したためその処理は実装していません。
 [ Server側 ]
namespace SampleTcpServer {
 using namespace System;
 using namespace System::ComponentModel;
 using namespace System::Collections;
 using namespace System::Windows::Forms;
 using namespace System::Data;
 using namespace System::Drawing;
 using namespace System::Net;   // <---★追加★
 using namespace System::Net::Sockets; // <---★追加★
 using namespace System::Text;   // <---★追加★
  /// <summary>
 /// Form1 の概要
 //:<略>
 /// </summary>
 public ref class Form1 : public System::Windows::Forms::Form
 {
 public:
  Form1(void)
  {
   InitializeComponent();
   //
   //TODO: ここにコンストラクタ コードを追加します
   //
  }
 protected:
  /// <summary>
  /// 使用中のリソースをすべてクリーンアップします。
  /// </summary>
  ~Form1()
  {
   if (components)
   {
    delete components;
   }
  }
 private: System::Windows::Forms::Button^  button1;
 private: System::Windows::Forms::TextBox^  textBox1;
 protected:
 private:
  /// <summary>
  /// 必要なデザイナ変数です。
  /// </summary>
  System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
//  :<略>
#pragma endregion
  TcpListener ^f1_server;
  TcpClient     ^f1_client;
  NetworkStream ^f1_stream;
 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
  {
   String ^host_str = gcnew String("localhost");
   String ^command_str = gcnew String("Ack");
   array<Byte>^send_bytes = gcnew array<System::Byte>(1024); // 受信用
   String ^RecvData;           // 受信Stringデータ(Byte型から変換)
   array<Byte>^recv_bytes = gcnew array<System::Byte>(1024); // 受信用
   int  rcv_leng;            // 受信文字数
   int port = 7777;           // PortNo
   f1_server = gcnew TcpListener(Net::Dns::GetHostEntry(host_str)->AddressList[0], port); // オブジェクト生成
   f1_server->Start();       // 接続待ち開始
   
   f1_client = f1_server->AcceptTcpClient(); // 接続していきたClinet取得
   // コマンド受信
   rcv_leng = 0;
   f1_stream = f1_client->GetStream();
   rcv_leng = f1_stream->Read(recv_bytes, 0, recv_bytes->Length);
     RecvData = Encoding::ASCII->GetString(recv_bytes, 0, rcv_leng);
   if(rcv_leng!=0) {
    textBox1->Text = RecvData;
    command_str = "Ack";
   }
   else {
    command_str = "Nack";
   }
   // Ack送信
   send_bytes = Encoding::ASCII->GetBytes(command_str);  // StringをByteに変換
   f1_stream->Write(send_bytes, 0, send_bytes->Length);  // コマンド送信

   // 切断
   f1_stream->Close();
   f1_client->Close();
   f1_server->Stop();
  }
 };
}
 
[ Client側 ]
namespace SampleTcpClient {
 using namespace System;
 using namespace System::ComponentModel;
 using namespace System::Collections;
 using namespace System::Windows::Forms;
 using namespace System::Data;
 using namespace System::Drawing;
 using namespace System::Net;   // <---★追加★
 using namespace System::Net::Sockets; // <---★追加★
 using namespace System::Text;   // <---★追加★
 /// <summary>
 /// Form1 の概要
 //:<略>
 /// </summary>
 public ref class Form1 : public System::Windows::Forms::Form
 {
 public:
  Form1(void)
  {
   InitializeComponent();
   //
   //TODO: ここにコンストラクタ コードを追加します
   //
  }
 protected:
  /// <summary>
  /// 使用中のリソースをすべてクリーンアップします。
  /// </summary>
  ~Form1()
  {
   if (components)
   {
    delete components;
   }
  }
 private: System::Windows::Forms::Button^  button1;
 private: System::Windows::Forms::TextBox^  textBox1;
 protected:
 private:
  /// <summary>
  /// 必要なデザイナ変数です。
  /// </summary>
  System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
// :<略>
#pragma endregion
  TcpClient     ^f1_client;
  NetworkStream ^f1_stream;

  //-----------------------------------------------------
  //  Server に接続し、 "CMD1"送信し、応答受信して
  //  受信した文字列を textBox1に表示
  //-----------------------------------------------------
 private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
  {
   String ^host_str = gcnew String("localhost");
   String ^command_str = gcnew String("CMD1");
   array<Byte>^send_bytes = gcnew array<System::Byte>(1024); // 受信用
   String ^RecvData;           // 受信Stringデータ(Byte型から変換)
   array<Byte>^recv_bytes = gcnew array<System::Byte>(1024); // 受信用
   int  rcv_leng;            // 受信文字数
   
   //String ^ipaddress_str = gcnew String("127.0.0.1");  // Server IPAddress
   int port = 7777;          // PortNo
   // Serverへ接続
   //f1_client = gcnew TcpClient(ipaddress_str, port);
   f1_client = gcnew TcpClient(host_str, port);
   // 接続後、コマンド送信
   f1_stream = f1_client->GetStream();
   send_bytes = Encoding::ASCII->GetBytes(command_str);  // StringをByteに変換
   f1_stream->Write(send_bytes, 0, send_bytes->Length);  // コマンド送信
   // 応答受信
   rcv_leng = f1_stream->Read(recv_bytes, 0, recv_bytes->Length);
   RecvData = Encoding::ASCII->GetString(recv_bytes, 0, rcv_leng);
   textBox1->Text = RecvData;
   // 切断
   f1_stream->Close();
   f1_client->Close();
  }
 };
}
 
Semaphore
2014-10-01
 今回は、プロセスやスレッドで 排他制御に用いる
 Semaphore について作成してみました。
 Semaphore の説明を始めると長くなるため
 ここでは省略させていただければと思います。
 第16回のMutexのときにちょっとふれましたが
 Mutexは、同じスレッドで Mutex を1つしか取得できませでした。
 Semaphoreは、指定回数分同じスレッドで取得できます。
 < サンプルの概要 >
 Form起動時に Semaphore生成(max=2)、
 button2[ThreadStart]押しで、スレッド起動し、Semaphoreを3つ取得。
 3つめ取得で、解放待ちになります。
 button1[One Release Semaphore]押しで、1つ解放されるため
 3つめ所得で待ちが解放されて、スレッドの処理が進みます。
 この時点でスレッドが Semaphoreを2つ取得していますので
 2つ解放してスレッド終了します。
 また、button2から同じ動作を再開できます。
 Semaphore取得待ちで、Formを閉じるとスレッドが残って
 プロセスも残ってしまうため、Exitボタンの許可禁止制御をして
 必ずbutton1[One Release Semaphore]押して、スレッド閉じてから
 Exitボタンが押せるようにしてあります。

#pragma once
#include <windows.h>    // <--- 追加
namespace Semaphore1 {
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Threading;        // <--- ★追加★
    /// <summary>
    /// Form1 の概要
    ///
    /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての ..resx ファイルに関連付けられた
    ///          マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
    ///          変更する必要があります。この変更を行わないと、
    ///          デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
    ///          正しく相互に利用できなくなります。
    /// </summary>
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
        }
    protected:
        /// <summary>
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        ~Form1()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Button^  button1;
    private: System::Windows::Forms::Button^  button2;
    private: System::Windows::Forms::Button^  button3;
    protected:
    private:
        /// <summary>
        /// 必要なデザイナ変数です。
        /// </summary>
        System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
    :<略>
#pragma endregion
    // Member
        // Thread処理用メンバ宣言
        Thread^ WorkThread;
        ThreadStart^ WorkThreadDelegate;
        HANDLE  hSemaph;    // <----- Semaphore用ハンドラ変数宣言
    // Method
        // Thread処理メソッド
        void ThreadProcessing(void)
        {
            MessageBox::Show("Threadで資源2個取得します。OK押し後、Relaseボタンをおしてください。");
            GetSemaphore();        // Semaphore 1個取得
            GetSemaphore();        // Semaphore 2個取得(Createで2個分枠とっているので、ここまで取得できる。)
            GetSemaphore();        // Semaphore 1つ取得待ち( Releaseボタン押し待ち )
            MessageBox::Show("Threadで、また1つ資源取得しました。"); // 1つ解放されるとここへ来れる。
            RelSemaphore();        // 上記で 2個目を取得しているので解放。
            RelSemaphore();        // 1個目を解放。これで取得すう0となる。
        }

        // Make Semaphore
        void CreateSemaph(void) {
            // Sempahrore 初期カウント=2、最大カウント=2
            hSemaph = CreateSemaphore( NULL, 2, 2, L"test1_Semaphore_HANDLE" );
        }
        // Get Semaphore
        void GetSemaphore(void) {
            WaitForSingleObject(hSemaph, INFINITE);    // 資源取得待ち (Timeout待ちもできるが、今回は無限待ち)
        }

        // Release Semaphore
        void RelSemaphore(void) {
            LONG previous = 0;                        // それまでのカウント
            ReleaseSemaphore(hSemaph, 1, NULL);        // Semaphore解放
        }

        // Close Semaphore
        void CloseSemaphore(void) {
            if(hSemaph!=nullptr)
                CloseHandle(hSemaph);                // Semaphore閉じ
        }

    // Load Event
    private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
        {
             button1->Enabled = false;    // Releaseボタン禁止
            // Semaphore生成
            CreateSemaph();
        }
    // End Event
    private: System::Void Form1_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^  e) {
             CloseSemaphore();
         }
    // Releaseボタン
    private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
        {
            button3->Enabled = true;    // Exitボタン許可
            button2->Enabled = true;    // ThreadStartボタン許可
            button1->Enabled = false;    // Releaseボタン禁止
            RelSemaphore();                // Semaphore解放(1つ分解放)
        }
    // Thread生成ボタン
    private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
            button3->Enabled = false;    // Exitボタン禁止
            button2->Enabled = false;    // Threadボタン禁止
            button1->Enabled = true;    // Releaseボタン許可
            // Thread生成
            WorkThreadDelegate = gcnew ThreadStart(this, &Semaphore1::Form1::ThreadProcessing);
            WorkThread = gcnew Thread(WorkThreadDelegate);
            WorkThread->Start();
        }
    // Exitボタン
    private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
             Close();
         }
};
}
 
(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
Mutex
2014-06-11
 今回は、プロセスやスレッドで 排他制御に用いる
 Mutex について作成してみました。
 Mutex の説明を始めると長くなるため
 ここでは省略させていただければと思います。
 アプリケーション本体で、Mutexを生成、取得し
 スレッドを起動、スレッド側でも取得実行。(すでに取得されているため待ち)
 Releaseボタン(button2)を押すと、Mutex解放するので、スレッド側で
 取得でき、MessageBoxを表示するというものです。
 実装上、ありえないと思いますが、同じスレッドで Mutex を2度待つことはできません。
 自スレッドで、Mutex取得後、もう一度取得待ちを呼び出してもすぐ取得となり
 プログラムが先へ進んでしまいます。
 待たせたい場合は、Semaphore で数を指定して実装すれば実現できると思いますが
 それは、また別の機会にと思います。

#include <windows.h> // <--- 追加
namespace Mutex1 {
 using namespace System;
 using namespace System::ComponentModel;
 using namespace System::Collections;
 using namespace System::Windows::Forms;
 using namespace System::Data;
 using namespace System::Drawing;
 using namespace System::Threading;    // <--- ★追加★
 public ref class Form1 : public System::Windows::Forms::Form
 {
 public:
  Form1(void)
  {
   InitializeComponent();
  }
 protected:
  ~Form1()
  {
   if (components)
   {
    delete components;
   }
  }
 protected:
 private: System::Windows::Forms::Button^  button2;
 private:
  System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
  void InitializeComponent(void)
  {
   :<略>
  }
#pragma endregion

 // Member
  // Thread処理用メンバ宣言
  Thread^ WorkThread;
  ThreadStart^ WorkThreadDelegate;
  HANDLE hMutex;    // <----- Mutex用ハンドラ変数宣言
 // Method
  // Thread処理メソッド
  void ThreadProcessing(void)
  {
   GetMutex();     // Mutex取得待ち
   MessageBox::Show("Threadで資源取得しました。");
   RelMutex();     // Mutex解放
  }

  // Make Mutex
  void CreateMutex(void) {
   hMutex = ::CreateMutex( NULL, FALSE, L"MutexSample1." ); // Mutex生成
  }

  // Get Mutex
  void GetMutex(void) {
   WaitForSingleObject(hMutex, INFINITE);   // 資源取得待ち (Timeout待ちもできるが、今回は無限待ち)
  }

  // Release Mutex
  void RelMutex(void) {
   ReleaseMutex(hMutex);  // Mutex解放
  }

  // Close Mutex
  void CloseMutex(void) {
   if(hMutex!=nullptr)
    CloseHandle(hMutex); // CloseMutex
  }

 // Load Event
 private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
  {
   // Mutex生成
   CreateMutex();
   GetMutex();     // Mutex取得
   // Thread生成
   WorkThreadDelegate = gcnew ThreadStart(this, &Mutex1::Form1::ThreadProcessing);
   WorkThread = gcnew Thread(WorkThreadDelegate);
   WorkThread->Start();
  }
 // EndEvent
 private: System::Void Form1_FormClosing(System::Object^  sender, System::Windows::Forms::FormClosingEventArgs^ e)
  {
   CloseMutex();  // Mutexを閉じる。
  }
 // Release
 private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e)
  {
   button2->Enabled = false;
   RelMutex();     // Mutex解放
  }
};
}

(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
別アプリケーション実行終了待ち
2014-05-06
前回は別アプリケーション起動をまとめてみました。
そのときは、無限終了待ちでしたが
今度は、終了Eventを登録して、別アプリケーション終了時に
Eventが発生し、NotepadEndEvent()が callされれます。

namespace StartOtherExe {
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Diagnostics;
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: ここにコンストラクタ コードを追加します
            //
        }
        :<略>
        void InitializeComponent(void)
        {
            :<略>
        }
#pragma endregion
    private:
        // Notepad終了Event処理メソッド
        void NotepadEndEvent(System::Object  ^sender, System::EventArgs ^e)
        {
            MessageBox::Show("Notepad終了しました。", "msg");
        }

    private: System::Void button1_Click(System::Object^  sender,
System::EventArgs^  e)
        {
            Process ^cmd = gcnew Process();
            cmd->StartInfo->FileName = "C:\\Windows\\System32\\notepad.exe";
// メモ帳指定
            cmd->StartInfo->Arguments = "C:\\TEMP\\Test.txt";
// 引数指定。今回は 開くファイル名
            cmd->Exited += gcnew System::EventHandler(this,
&Form1::NotepadEndEvent);    // 終了時のメソッド登録
            cmd->EnableRaisingEvents = true;
// Event発生を許可
            cmd->Start();
// メモ帳起動
        }
    };
}

(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
 
別アプリケーション実行
2014-03-14
 今回は、別のアプリケーションを起動する方法です。
 以下例は、メモ帳を引数で開くファイル指定(C:\TEMP\Test.txt")で起動します。
 また、メモ帳が終了するのを待つ例です。
namespace StartOtherExe {
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Diagnostics;    // <--★追加
    public ref class Form1 : public System::Windows::Forms::Form
    {
    public:
        Form1(void)
        {
            InitializeComponent();
        }

    :<略>
    private: System::Void button1_Click(System::Object^  sender,
System::EventArgs^  e)
             {
                 Process ^cmd = gcnew Process();
                 cmd->StartInfo->FileName =
"C:\\Windows\\System32\\notepad.exe";    // メモ帳指定
                 cmd->StartInfo->Arguments = "C:\\TEMP\\Test.txt";
// 引数指定。今回は 開くファイル名
                 cmd->Start();
// メモ帳起動
                 cmd->WaitForExit();        // ()内にmsec単位で exe修了を待つことができます。無は無限待ち。
             }
    };
}

(WindowsアプリケーションForm (Framework3.5) VS2008 VC++環境でのお話しです。)
1