0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DXライブラリを使用したSocketクライアントの作成

Posted at

概要

作業目的

DXライブラリを利用してSocketクライアントを作成します。

環境・前提条件

本件手順では、以下Windows環境にMicrosoft Visual Studioがインストールされている前提とします。

  • エディション:Microsoft Windows 10 Pro
  • システムの種類:64 ビット オペレーティング システム、x64 ベース プロセッサ
  • バージョン:22H2
  • OSビルド 19045.4651
  • エクスペリエンス:Windows Feature Experience Pack 1000.19060.1000.0
  • Microsoft Visual Studio Community 2022 (64 ビット) :Version 17.9.7
  • DXライブラリ Windows版 VisualStudio( C++ )用:Ver 3.24d
  • (2024年7月21日現在)

参考ページ

その他の参考となるページは以下に記載しています。

DXライブラリ準備

DXライブラリの事前設定

下記ページから、DXライブラリの設定準備を進めてください。

DXライブラリでSocket処理を利用する場合の注意点

Socket処理のサンプル

下記ページにサンプルがあります。

送信データサイズの解除

事前に"SetUseDXNetWorkProtocol"関数を実行して、無効化する必要があります。


SetUseDXNetWorkProtocol( FALSE );

Socketクライアントの作成

処理概要

Socketクライアントとしてメッセージを送信するアプリケーションを作成します。

プログラムソース

[手順1.]ソースの作成

以下のソースについてコピー&ペーストします。
保存する場合にはテキストファイルを以下の形式としています。

(テキストファイルの仕様)

  • 改行コード:SJIS
  • 改行コード:CR+LF
dxtest.cpp

/* ---------------------------------------------------------------------------------------------- 
 * 
 * プログラム概要   : DXライブラリ用Socket接続
 * バージョン       : 1.0.0.0
 * プログラム名     : dxtest.exe
 * ファイル名       : dxtest.cpp
 * 処理概要         : メイン処理
 * Ver1.0.0.0作成日 : 2024/07/21 10:32:37
 * 最終更新日       : 2024/07/21 10:32:37
 * 
 * Copyright (c) 2023-2024 Techmilestone, All rights reserved.
 * 
 * ---------------------------------------------------------------------------------------------- */

#include "DxLib.h"

// ----------------------------------------
// グローバル変数定義
// ----------------------------------------

	// ----------------------------------------
	// 変数初期化(フレーム処理)
	// ----------------------------------------

	// フレーム処理用定数
	static const int SAMPLE_FRAME_COUNT = 60;   // フレームのサンプル数
	static const int FPS                = 60;   // 想定のFPS値 (待ち時間の算出用)

	// FPS算出用変数(フレーム定義)
	static int frame_count;                     // サンプルフレームのカウンタ数
	static int total_frame_count;               // 処理したフレームの合計数

	// FPS算出用変数(時間定義)
	static int checkpoint_time;                 // 定点時刻(チェックポイントごとの時刻)
	static int wait_time;                       // 待ち時間(Sleep関数を利用するために単位はミリ秒)

	// FPS算出用変数(FPS数)
	static float ave_fps;                       // 実測のFPS値

	// ----------------------------------------
	// 変数初期化(マウス処理)
	// ----------------------------------------

	// マウス処理情報
	static int msx;                     // X座標
	static int msy;                     // Y座標
	static int get_mouse_input;         // マウスの押した状態取得
	static unsigned int get_button[8];  // ボタンの押した状態
	static int wheel_rot_vol;           // ホイールの回転量

	// ----------------------------------------
	// 変数初期化(画像処理)
	// ----------------------------------------

	// 画像ハンドル
	static int pic_handle;              // 背景用画像

	// ----------------------------------------
	// 変数初期化(Socket処理)
	// ----------------------------------------
	static int  net_handle;      // ネットワークハンドル
	static char rcv_buf[1024];   // 受信用バッファ
	static char snd_buf[1024];   // 送信用バッファ

// ----------------------------------------
// フレーム初期化
// ----------------------------------------
int WindowFrameInit(){

	// Log.txtの出力抑止
	SetOutApplicationLogValidFlag(FALSE);

	// ウインドウモードにする
	// DxLib_Initより前に行う
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK ) {

		// 異常終了
		return -1;

	}

	// ウィンドウサイズ変更
	SetGraphMode( 1024 , 768 , 32 );
	SetWindowSize( 1024 , 768 );

	// ウインドウがアクティブではない状態でも処理を続行する
 	SetAlwaysRunFlag(TRUE);

	// 2つ以上同時に起動できるかどうかを設定する。
 	SetDoubleStartValidFlag(TRUE);

	// マウス表示オン
    SetMouseDispFlag(TRUE);

	// 正常終了
	return 0;

}

// ----------------------------------------
// DX表示ライブラリ初期化
// ----------------------------------------
int CustomDxlibInit(){

	// DXライブラリ初期化
	if (DxLib_Init() != 0){

		// 異常終了
		return -1;

	}

	// 描画先を裏画面に設定
	SetDrawScreen(DX_SCREEN_BACK); 

	// 画像ハンドル
	pic_handle = LoadGraph("bmp/back.bmp"); // 画像のロード

	// 正常終了
	return 0;

}

// ----------------------------------------
// DX表示ライブラリ終了処理
// ----------------------------------------
void CustomDxlibEnd(){

	DxLib_End();   // DXライブラリ使用の終了処理

}

// ----------------------------------------
// Fps算出処理の初期化
// ----------------------------------------
void FpsParamInit(){

	// 変数初期化
	ave_fps           = 0;    // ave_fps初期化
	frame_count       = 0;    // frame_count初期化
	total_frame_count = 0;    // total_frame_count初期化

	// 最初フレームの「定点時刻(checkpoint_time)」定義
	checkpoint_time = GetNowCount();

}

// ----------------------------------------
// 定点時刻(checkpoint_time)の更新、平均Fps算出
// ----------------------------------------
void FpsUpdate(){

	// 変数定義
	int tmp_now_time;    // 現在時刻

	// サンプルフレーム数に達した場合の内部処理
	// 「定点時刻(checkpoint_time)」の更新、「平均ave_fps」算出
	if( frame_count == SAMPLE_FRAME_COUNT ){ 

		// 現在の時間の取得
		tmp_now_time = GetNowCount();

		// 「平均ave_fps」算出処理
		ave_fps = (float)SAMPLE_FRAME_COUNT*1000.f / (tmp_now_time - checkpoint_time);

		// 「フレームのカウンタ数」の初期化
		frame_count = 0;

		// SAMPLE_FRAME_COUNTごとに「定点時刻」を更新
		checkpoint_time = tmp_now_time;

	}

	// 「フレームのカウンタ数」の加算
	frame_count++;

	// 「合計フレームのカウンタ数」の加算
	total_frame_count++;

}

// ----------------------------------------
// FPSウエイト処理
// ----------------------------------------
void FpsWait(){

	// 現在時刻と「定点時刻(checkpoint_time)」との差分時間を算出
	// それから待ち時間(wait_time)を算出
	wait_time = ( frame_count*1000 / FPS ) - (GetNowCount() - checkpoint_time); // frame_countからの理論時刻と実機からの現在時間との差分を算出する

	// ウエイト処理
	if( wait_time > 0 ){
		Sleep(wait_time); // wait_timeの時間(ミリ秒)だけ待機を行う
	}

}

// ----------------------------------------
// 表示処理
// ----------------------------------------
void CustomDxlibDraw(){

	// 画面を消す
	ClearDrawScreen();

	// 背景表示
	DrawGraph( 0, 0, pic_handle, TRUE );

	// 文字列表示
	DrawFormatString(  5,   0, GetColor(255,255,255), "受信メッセージ:%s", rcv_buf);
	DrawFormatString(  5,  17, GetColor(255,255,255), "実測FPS値:%.1f", ave_fps);

	// 裏画面を表画面に反映
	ScreenFlip();

}

// ----------------------------------------
// socket初期化
// ----------------------------------------
int CustomSocketInit(){

	// 変数定義
	IPDATA ip;                   // 接続用IPアドレスデータ

	// DXライブ独自のsocket仕様の機能を使用しない
	SetUseDXNetWorkProtocol( FALSE );

	// IPアドレスを設定
	ip.d1 = 127 ;
	ip.d2 = 0 ;
	ip.d3 = 0  ;
	ip.d4 = 1 ;

	// 通信を確立
	net_handle = ConnectNetWork( ip, 11600 ) ;

	// ハンドルの正常性確認
	if( net_handle == -1 ){
		// 異常終了
		return -1;
	}else{
		// データ送信
		sprintf_s(snd_buf,"接続要求\n");
		NetWorkSend(net_handle, snd_buf, lstrlen(snd_buf)) ;
		// 正常終了
		return 0;
	}

}

// ----------------------------------------
// socket終了処理
// ----------------------------------------
void CustomSocketEnd(){

	// ネットワークハンドルの解放
	CloseNetWork(net_handle);

}

// ----------------------------------------
// データ送受信
// ----------------------------------------
void CustomSocketRecSnd(){

	// 変数定義
	int data_size;               // 受信データ時のデータサイズ

	// 取得していない受信データ量を得る
	data_size = GetNetWorkDataLength(net_handle);

	// 受信データ量が0より大きい場合
	if( data_size > 0 ){

		// バッファクリア
		memset(rcv_buf, 0, sizeof(rcv_buf));

		// 受信したデータをバッファに取得
		NetWorkRecv(net_handle, rcv_buf, sizeof(rcv_buf));

		// サーバ側にデータ送信
		sprintf_s(snd_buf,"受信完了\n");
		NetWorkSend(net_handle, snd_buf, lstrlen(snd_buf));

	}

}


// ----------------------------------------
// メイン処理
// ----------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){

	// ----------------------------------------
	// 事前処理
	// ----------------------------------------

	// Windows画面の事前処理
	if (WindowFrameInit() != 0){

		// ダイアログの出力
		MessageBox( NULL, "異常終了 ChangeWindowMode", "警告", MB_OK );
		return -1;

	}

	// DXライブラリ初期化
	if (CustomDxlibInit() != 0){    

		// ダイアログの出力
		MessageBox( NULL, "異常終了 DxLib_Init", "警告", MB_OK );
		return -1;

	}

	// FPS処理初期化
	if (CustomSocketInit() != 0){    

		// ダイアログの出力
		MessageBox( NULL, "異常終了 Socket_Init", "警告", MB_OK );
		return -1;

	}

	// FPS処理初期化
	FpsParamInit();

	// ----------------------------------------
	// メイン処理(ループ処理)
	// ----------------------------------------

	// 終了処理がされるまで、ループ処理
	while( ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0 ){

		// 関数処理
		CustomSocketRecSnd();  // socketデータの送受信
		FpsUpdate();           // checkpoint_time更新、平均Fps算出
		CustomDxlibDraw();     // 表示処理
		FpsWait();             // ウエイト処理

	}

	// ----------------------------------------
	// 終了処理
	// ----------------------------------------

	// socket終了処理
	CustomSocketEnd();

	// DXライブラリ終了処理
	CustomDxlibEnd();

	// 正常終了
	return 0;

}

/* ---------------------------------------------------------------------------------------------- 
 * ソース終了
 * ---------------------------------------------------------------------------------------------- */

[手順2.]ソースのビルドを行う。

Visual Studio Communityを利用してビルドを行ってください。

Socketクライアントの機能説明

はじめに

Socket利用のために、実装が必要となるDXライブラリの関数を記載します。

1.変数定義

以下の変数を定義します


static int  net_handle;      // ネットワークハンドル
static char rcv_buf[1024];   // 受信用バッファ
static char snd_buf[1024];   // 送信用バッファ

2.サーバに接続

connect関数でリモートソケット(サーバ側ソケット)に接続します


// DXライブ独自のsocket仕様の機能を使用しない
SetUseDXNetWorkProtocol( FALSE );

// IPアドレスを設定
ip.d1 = 127 ;
ip.d2 = 0 ;
ip.d3 = 0  ;
ip.d4 = 1 ;

// 通信を確立
net_handle = ConnectNetWork( ip, 11600 ) ;

3.サーバにデータを送信

NetWorkSend関数で接続済みサーバのソケットにデータを送信します。


// データ送信
sprintf_s(snd_buf,"接続要求\n");
NetWorkSend(net_handle, snd_buf, lstrlen(snd_buf)) ;

4.サーバからデータを受信

サーバからのデータ受信を検知します。


// 取得していない受信データ量を得る
data_size = GetNetWorkDataLength(net_handle);

// 受信データ量が0より大きい場合
if( data_size > 0 ){

	// バッファクリア
	memset(rcv_buf, 0, sizeof(rcv_buf));

	// 受信したデータをバッファに取得
	NetWorkRecv(net_handle, rcv_buf, sizeof(rcv_buf));

}

参考情報

動作確認

事前処理:「TCP/IPテストツール」のインストール

以下サイトからSocketクライアント用フリーツールを取得します。

上記のアプリケーションをインストールします。

動作確認:接続確認

以下のとおりにクライアントがサーバからのメッセージを受信しています。

[手順1.]「TCP/IPテストツール」を起動します。

[手順2.]ビルドしたアプリケーションを起動します。

[手順3.]「TCP/IPテストツール」でデータを受信したことを確認します。

動作確認:データ送信

[手順1.]「TCP/IPテストツール」でデータを送信します。

[手順2.]ビルドしたアプリケーションがデータを受信したことを確認します。

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?