ページ 1 / 1
DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 18:37
by わからんこ
コード:
#include "GV.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode(TRUE);
SetMainWindowText( "サーバー" ) ;
char StrBuf[MAX_CONNECT_NUM][ 256 ] ; // データバッファ
int NetHandle[MAX_CONNECT_NUM],LostHandle[MAX_CONNECT_NUM]; // ネットワークハンドル
int DataLength[MAX_CONNECT_NUM]; ; // 受信データ量保存用変数
IPDATA Ip[MAX_CONNECT_NUM] ; // 接続先IPアドレスデータ
int Num,Flag;
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
// 接続してくるのを待つ状態にする
PreparationListenNetWork( 10000 ) ;
//初期化
for(int i=0;i<MAX_CONNECT_NUM;i++){
strcpy( StrBuf[i], "" ) ;
NetHandle[i] = -1 ;
}
//ESCキーが押されるまでループ
while( !ProcessMessage() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 &&ClearDrawScreen()==0)
{
//接続が切れてるかチェック
for(int i=0;i<MAX_CONNECT_NUM;i++){
LostHandle[i]=GetLostNetWork();
if(LostHandle[i]==NetHandle[i])NetHandle[i]=-1;
}
//配列番号を決める
for(int i=0;i<MAX_CONNECT_NUM;i++){
if(NetHandle[i]==-1){
Num=i;
Flag=0;
break;
}else{
Flag=1;
}
}
//接続人数限界以上じゃなかったらつなげる
if(Flag != 1)
NetHandle[Num] = GetNewAcceptNetWork();
//ip保存
GetNetWorkIP(NetHandle[Num] , &Ip[Num]) ;
int y=0;
//接続者の名前を表示
for(int i=0;i<MAX_CONNECT_NUM;i++){
//データを受信してる
if( GetNetWorkDataLength( NetHandle[i] ) != 0 ){
// データ受信
DataLength[i] = GetNetWorkDataLength( NetHandle[i] ) ; // データの量を取得
NetWorkRecv( NetHandle[i] , StrBuf[i] , DataLength[i] ); // データをバッファに取得
}else{
}
if(NetHandle[i]!=-1){
// 受信したデータを描画
DrawFormatString( 0, y,GetColor( 255 , 255 , 255 ), "接続中 IP:%d.%d.%d.%d 名前:%s "
,Ip[i].d1,Ip[i].d2,Ip[i].d3,Ip[i].d4 ,StrBuf[i] ) ;
y+=FONT_SIZE;
// 受信成功のデータを送信
NetWorkSend( NetHandle[i] , "接続成功" , 9 ) ;
}
}
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
http://dixq.net/forum/viewtopic.php?f=3&t=10029
自分なりに複数人接続できる事を目指してコードを書いてみましたが
うまくいきません。
PreparationListenNetWorkを使って接続受付中状態で他の処理を行うことはできますか?
またループの度にGetNewAcceptNetWork();を行うのはダメですか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 18:47
by softya(ソフト屋)
たぶん無理だと思います。※あとで調べます。
最近DXライブラリやwinsockでゲームサーバーを書く人が多いのですが、実際の所サーバー運用はどうされる予定でしょうか?
家庭用のPCを使いますか? ・・・ 熱問題や信頼性、電気料金、回線速度、冷房費用、24時間接続など問題は山積みです。
レンタルサーバーを使いますか? ・・・ DXライブラリやwinsockはLinuxやUNIXなので使えません。
まず、ここをクリアされたほうが良いと思います。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 18:55
by わからんこ
そんな大きなものでなく
友達4人ぐらいと、通信できればいいな、と考えている次第です。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:05
by softya(ソフト屋)
調べてみました。
>PreparationListenNetWorkを使って接続受付中状態で他の処理を行うことはできますか?
出来ます。
>またループの度にGetNewAcceptNetWork();を行うのはダメですか?
出来ます。
と言うことで出来ますが、複数の同時接続だとスレッド化を考えないとマズイと思いますがDXライブラリの通信がスレッドで利用可能か確認できませんでした。
わからんこ さんが書きました:そんな大きなものでなく
友達4人ぐらいと、通信できればいいな、と考えている次第です。
友だちと遊ぶ時に自宅のPCの一台をサーバー用として開放するなら問題ないと思います。
サーバーを管理できる人がかならずサーバーアプリを起動する必要がありますけど。
ルータのポート開けも必要で、光回線など強力なものが望ましくADSLなど貧弱な回線の持ち主がサーバーに成るのは避けたほうが良いです。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:18
by わからんこ
一対一の通信には成功したので、次のステップとして
複数人の通信を勉強しようと考え始めました。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:32
by softya(ソフト屋)
考えて見ましたがスレッドを使わずに、うまく組んでリアルタイム・アクション系じゃなければ多少遅延しても通信は出来ると思います。
で現状の「うまくいきません」の具体的な内容を教えて下さい。それをどうやって確認したのかテスト手順も必要な情報です。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:38
by わからんこ
ハンドルされていない例外が発生しました。
相手と繋がった後、表示されてとまってしまいます。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:39
by softya(ソフト屋)
わからんこ さんが書きました:ハンドルされていない例外が発生しました。
相手と繋がった後、表示されてとまってしまいます。
サーバーとクライアントのどちらが停止しますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:43
by わからんこ
一対一の通信は友達にプログラムを渡し起動してもらい
通信を行いテストしてみました。
今回の複数人のテスト方法は同じパソコン内でサーバー側、クライアント側、起動して実験していますが、
サーバー側がとまってしまいます。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:45
by softya(ソフト屋)
デバッグ開始(F5)で起動すれば問題のあるところで止まると思います。
何処の命令でしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:54
by わからんこ
すいません。クライアント側でした。
Client.exe の 0xda9000f7 でハンドルされていない例外が発生しました: 0xC0000005: Access violation
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 19:57
by わからんこ
コード:
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
char StrBuf[ 256 ] ; // データバッファ
IPDATA Ip ; // 接続用IPアドレスデータ
int NetHandle ; // ネットワークハンドル
int DataLength ; // 受信データ量保存用変数
//ウィンドウに切り替えと多重起動の許可
SetDoubleStartValidFlag( TRUE ) ;
ChangeWindowMode(TRUE);
SetMainWindowText( "クライアント" ) ;
if( DxLib_Init() == -1 ) // DXライブラリ初期化処理
{
return -1; // エラーが起きたら直ちに終了
}
while( !ProcessMessage()){
// IPアドレスを設定( ここにある4つのIP値は仮です )
Ip.d1 = 192 ;
Ip.d2 = 168 ;
Ip.d3 = 11 ;
Ip.d4 = 50 ;
// 通信を確立
NetHandle = ConnectNetWork( Ip, 10000 ) ;
if(NetHandle!=-1)break;
}
// 確立が成功した場合のみ中の処理をする
if( NetHandle != -1 )
{
// データ送信
NetWorkSend( NetHandle , "接続者の名前" , 13 ) ;
}
while( CheckHitKey( KEY_INPUT_ESCAPE ) == 0&&ClearDrawScreen()==0){
// データがくるのを待つ
while( !ProcessMessage() ){
// 取得していない受信データ量を得る
DataLength = GetNetWorkDataLength( NetHandle ) ;
// 取得してない受信データ量が0じゃない場合はループを抜ける
if( DataLength != 0 ) break ;
}
// データ受信
NetWorkRecv( NetHandle , StrBuf , DataLength ) ; // データをバッファに取得
// 受信したデータを描画
DrawString( 0 , 0 , StrBuf , GetColor( 255 , 255 , 255 ) ) ;
DataLength=0;
}
// 接続を断つ
CloseNetWork( NetHandle ) ;
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
クライアント側はテストの為名前だけ送っています
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 21:22
by softya(ソフト屋)
softya(ソフト屋) さんが書きました:デバッグ開始(F5)で起動すれば問題のあるところで止まると思います。
何処の命令でしょうか?
こちらの件はどうなっていますか?
必要なので聞いていますので必ず回答をお願いします。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 22:54
by わからんこ
わからんこ さんが書きました:すいません。クライアント側でした。
Client.exe の 0xda9000f7 でハンドルされていない例外が発生しました: 0xC0000005: Access violation
これでは回答になっていませんか?
これはサーバー側がメッセージを送ったら、このエラーがでてしまいます。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 22:58
by softya(ソフト屋)
わからんこ さんが書きました:わからんこ さんが書きました:すいません。クライアント側でした。
Client.exe の 0xda9000f7 でハンドルされていない例外が発生しました: 0xC0000005: Access violation
これでは回答になっていませんか?
これはサーバー側がメッセージを送ったら、このエラーがでてしまいます。
はい。これではClient.exe の何処かでメモリアクセスの範囲外例外が出たことしかわかりません。
何処での情報が抜けています。
わからんこさんが自分で直せる方法を理解しないと行けないのでお聞きしてます。
直すのは私ではなく、わからんこさんですよ。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 23:29
by わからんこ
すいません。
色々弄っていると、
1>LINK : fatal error LNK1168: ファイル E:\Client\Debug\Client.exe を開いて書き込むことができません。
このエラーがでてしまって、先ほどのエラーが出せませんので、返事がすることが出来なくなってしまいました。。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月25日(水) 23:32
by softya(ソフト屋)
わからんこ さんが書きました:すいません。
色々弄っていると、
1>LINK : fatal error LNK1168: ファイル E:\Client\Debug\Client.exe を開いて書き込むことができません。
このエラーがでてしまって、先ほどのエラーが出せませんので、返事がすることが出来なくなってしまいました。。
その場合はプログラムが終了していないのでタスクマネージャで、Client.exeをプロセス終了で強制終了してください。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 18:39
by わからんこ
コード:
#include "GV.h"
int NetHandle ; // 接続相手のネットワークハンドル
int StringY ; // 文字列表示領域の次に文字列を表示する時の行位置
char ScreenString[ CHAT_LINENUM ][ MAX_STRLENGTH + 1 ] ; // 画面に表示中のチャット文字列
char name[251];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//-----------------変数-----------------//
char StrBuf[ 81 ],StrBuf2[ 81 ];
IPDATA IP ; // 接続用IPアドレスデータ
int LostHandle;
int DataLength=0 ; // 受信データ量保存用変数
//---------------------------------------//
//-----------------初期設定------------------//
SetDoubleStartValidFlag( TRUE ) ;
ChangeWindowMode(TRUE);
SetMainWindowText( "クライアント" ) ;
if( DxLib_Init() == -1)return -1;
//-------------------------------------------//
//--------------------関数-------------------//
int ScreenStringAdd( char *AddString );
int ScreenStringDraw( void );
//-------------------------------------------//
// Ipの入力させる
int i,j,k;
// 接続先のIPの入力を促す
ScreenStringAdd( "アドレスを入力してください。" ) ;
ScreenStringAdd( "入力は半角で各IP値は『.』で区切り、隙間は入れないで下さい" ) ;
// 入力領域と文字出力領域との境界線を引く
DrawLine( 0 , CHAT_LINENUM * FONT_SIZE , 640 , CHAT_LINENUM * FONT_SIZE , GetColor(255,255,255) ) ;
while( !ProcessMessage() )
{
// IPの入力を行う
KeyInputSingleCharString( 0 , INPUT_LINE * FONT_SIZE + 2 , 80 , StrBuf , FALSE ) ;
// ピリオドが3つあるか調べる
j = 0 ;
for( i = 0 ; i < 80 ; i ++ )
{
if( StrBuf[ i ] == '.' ) j ++ ;
}
// もし3つピリオドがなかった場合は入力のし直し
if( j != 3 )
{
ScreenStringAdd( "IP値の数が間違っています" ) ;
continue ;
}
// 文字列からIPを抜き出す
j = 0 ;
k = 0 ;
i = 0 ;
while( !ProcessMessage() )
{
if( StrBuf[ i ] == '.' || StrBuf[ i ] == '\0' )
{
StrBuf2[ j ] = '\0' ;
switch( k )
{
case 0 :IP.d1 = atoi( StrBuf2 ) ; break ;
case 1 :IP.d2 = atoi( StrBuf2 ) ; break ;
case 2 :IP.d3 = atoi( StrBuf2 ) ; break ;
case 3 :IP.d4 = atoi( StrBuf2 ) ; break ;
}
k ++ ;
if( k == 4 ) break ;
j = 0 ;
}else{
StrBuf2[ j ] = StrBuf[ i ] ;
j ++ ;
}
i ++ ;
}
// 接続中表示
ScreenStringAdd( "接続中" ) ;
// 接続を試みる
NetHandle = ConnectNetWork(IP,10000) ;
// 接続に成功したらループから抜ける
if( NetHandle != -1 ) break ;
// 接続失敗表示
ScreenStringAdd( "接続は失敗しました" ) ;
}
// 接続成功表示
ScreenStringAdd( "接続しました" );
// 確立が成功した場合のみ中の処理をする
if( NetHandle != -1 ){
int Length;
KeyInputString( 0, INPUT_LINE * FONT_SIZE + 2,20 , name, FALSE);
Length = lstrlen(name) + 1 ;
// データ送信
NetWorkSend( NetHandle , name , Length ) ;
}
while( ProcessMessage()==0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && ClearDrawScreen()==0){
LostHandle=GetLostNetWork();
if(LostHandle==NetHandle)break;
// 取得していない受信データ量を得る
DataLength = GetNetWorkDataLength( NetHandle ) ;
// 取得してない受信データ量が0じゃない場合はループを抜ける
if( DataLength != 0 ){
// データ受信
NetWorkRecv( NetHandle , StrBuf , DataLength ) ; // データをバッファに取得
// 受信したデータを描画
DrawFormatString( 0, 0,GetColor( 255 , 255 , 255 ), "繋がってるかの状態 %s",StrBuf) ;
DataLength=0;
}
}
// 接続を断つ
CloseNetWork( NetHandle ) ;
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
アドバイスをもらい複数人の接続はうまくいくようになったのですが、
クライアント側がウィンドウの右端のバツを押して終了すると
バッファオーバーランが起こってしまうようになりました。
Run-Time Check Failure #2 - Stack around the variable 'StrBuf' was corrupted.
これは・・・StrBufに何か予期せぬ値が入っているから起こっているのでしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 18:47
by softya(ソフト屋)
定義を見るとStrBufはナル文字も含めて81文字までです。※ 漢字だと40文字までです。
データ受信時にDataLength に対して81文字のオーバーチェックを行なって下さい。
もしオーバーするならサーバー側で超えないようにするか受信側で工夫して下さい。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 19:21
by わからんこ
クライアント側に文字数を制限させました。
うまく行くことが出来ました。
次に本格的にデータをサーバーからクライアントに送るプログラムを作ってみます
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 19:26
by softya(ソフト屋)
ちなみに、こういう問題は良くセキュティ修正で聞くバッファーオーバーランの脆弱性と言います。
悪意のハッカーなら、このバッファーオーバーランを利用してPC内に潜入することが出来るわけです。
オンラインソフト作る場合は特に気をつけなくてはいけない問題です。
解決した場合は、解決チェックをお願いします。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 21:27
by わからんこ
知り合い同士の通信でも、PCに外部から侵入を許してしまう事はありますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 21:35
by softya(ソフト屋)
マイナーソフトだとPC侵入の可能性は低いでしょうがポートは常に無差別攻撃されていると思ったほうが良いでしょう。
そういう侵入経路を自動的に探すツールもあるみたいです。
なのでサーバー用に開放したポートに自分のプログラム以外の接続が起こることはあります。
それと怪しい接続の怪しいパケットが届く度に落ちていたら話にならないのである程度の堅牢性は必要と言えます。
もし偶然侵入されたらバックドアなどを仕掛けられて、何かの攻撃時の踏み台にされる可能性があります。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 22:06
by わからんこ
今、作っているのは簡単なプログラムですが、人に渡すモノなので
その様なことが起こるかも知れないプログラムを控えたほうがいいですね。
ある程度、プログラムを強固なものにすることは、私でも出来ますでしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月26日(木) 22:16
by softya(ソフト屋)
わからんこ さんが書きました:今、作っているのは簡単なプログラムですが、人に渡すモノなので
その様なことが起こるかも知れないプログラムを控えたほうがいいですね。
ある程度、プログラムを強固なものにすることは、私でも出来ますでしょうか?
やることは
1)バッファサイズをオーバーさせない
2)受信したデータの中身を検証して変なデータなら捨てる。
3)検証用の情報をデータに埋め込む
とちゃんとやれば大丈夫です。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 17:59
by わからんこ
コード:
#include "GV.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//-------------最初の設定--------------//
SetDrawScreen( DX_SCREEN_BACK );
ChangeWindowMode(TRUE);
SetMainWindowText( "サーバー" ) ;
if( DxLib_Init() == -1 )return -1;// エラーが起きたら直ちに終了
//-------------------------------------//
//-------------変数----------------//
char StrBuf[MAX_CONNECT_NUM][ 256 ];// データバッファ
int NetHandle[MAX_CONNECT_NUM],LostHandle[MAX_CONNECT_NUM]; // ネットワークハンドル
int DataLength[MAX_CONNECT_NUM]; ;// 受信データ量保存用変数
IPDATA Ip[MAX_CONNECT_NUM];// 接続先IPアドレスデータ
int Num,Flag,PortNum;
int count[MAX_CONNECT_NUM];
char Name[MAX_CONNECT_NUM][21];
//----------------------------------//
//---------------関数---------------//
int Net_Init(void);
//----------------------------------//
// 接続してくるのを待つ状態にする
PreparationListenNetWork( PortNum=Net_Init() ) ;
//初期化
for(int i=0;i<MAX_CONNECT_NUM;i++){
strcpy( StrBuf[i], "未受信" ) ;
strcpy( Name[i], "名前未受信" ) ;
NetHandle[i] = -1 ;
count[i]=0;
}
//ESCキーが押されるまでループ
while( ScreenFlip()==0&&ProcessMessage()==0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0&& ClearDrawScreen()==0)
{
//開放中のポート番号表示
DrawFormatString( 0, FONT_SIZE*2 ,GetColor(255,255,255),"現在開放中ポート番号 %d 番",PortNum);
//接続が切れてるかチェック
for(int i=0;i<MAX_CONNECT_NUM;i++){
LostHandle[i]=GetLostNetWork();
if(LostHandle[i]==NetHandle[i]){
strcpy( Name[i], "名前未受信" ) ;
strcpy( StrBuf[i], "未受信" ) ;
NetHandle[i]=-1;
count[i]=0;
}
}
//配列番号を決める
for(int i=0;i<MAX_CONNECT_NUM;i++){
if(NetHandle[i]==-1){
Num=i;
Flag=0;
break;
}else{
Flag=1;
}
}
//接続人数限界以上じゃなかったらつなげる
if(Flag != 1)
NetHandle[Num] = GetNewAcceptNetWork();
//ip保存
GetNetWorkIP(NetHandle[Num] , &Ip[Num]) ;
//接続者の名前を表示
for(int i=0;i<MAX_CONNECT_NUM;i++){
//データを受信してる
if( GetNetWorkDataLength( NetHandle[i] ) != -1 &&GetNetWorkDataLength( NetHandle[i])> sizeof( int )){
if(count[i]==0){
DataLength[i] = GetNetWorkDataLength( NetHandle[i] ) ; // データの量を取得
NetWorkRecv( NetHandle[i] , Name[i] , DataLength[i] );// データをバッファに取得
count[i]=1;
}else{
// データ受信
DataLength[i] = GetNetWorkDataLength( NetHandle[i] ) ; // データの量を取得
NetWorkRecv( NetHandle[i] , StrBuf[i] , DataLength[i] );// データをバッファに取得
DrawFormatString( 0, FONT_SIZE*10 ,GetColor(255,255,255),"Check");
}
}
if(NetHandle[i]!=-1){
// 受信したデータを描画
DrawFormatString( 0, 50+(FONT_SIZE*i),GetColor( 255 , 255 , 255 ), "No %d :接続中 IP:%d.%d.%d.%d 名前:%s "
,i,Ip[i].d1,Ip[i].d2,Ip[i].d3,Ip[i].d4 ,Name[i] ) ;
DrawFormatString( 0, 50+(FONT_SIZE*(i+1)),GetColor( 255 , 255 , 255 ), "受信内容:%s",StrBuf[i]);
}
}
//// 受信成功のデータを送信
//for(int i=0;i<MAX_CONNECT_NUM;i++){
// for(int j=0;j<MAX_CONNECT_NUM;j++){
// if(NetHandle[j]!=-1 && GetNetWorkDataLength( NetHandle[j])> sizeof( int )){
// DrawFormatString( 0, FONT_SIZE*10 ,GetColor(255,255,255),"hello world");
// NetWorkSend( NetHandle[j] , StrBuf[i] , DataLength[i]+1);
// }
// }
//}
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
相手が名前を入力してもらって名前を表示させることはできたのですが
クライアントが二回目以降データ送信してきたものはメッセージとして受け取って名前と同じ用に表示させたいのですが
表示することは出来ません。
名前のデータ受け取りが出来たので同じ要領かと思い書いたプログラムなのですが何がいけないのでしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 18:09
by softya(ソフト屋)
デバッガで動作を確認されましたか?
わからんこ さんが書きました:
相手が名前を入力してもらって名前を表示させることはできたのですが
クライアントが二回目以降データ送信してきたものはメッセージとして受け取って名前と同じ用に表示させたいのですが
表示することは出来ません。
名前のデータ受け取りが出来たので同じ要領かと思い書いたプログラムなのですが何がいけないのでしょうか?
この説明だけだと何が起こっているか、こちらには分かりません。
>表示することは出来ません。
じゃあ何が起こったのでしょうか?
あとインデントを正確に行うようにお願いします。バグの元にもなります。
「mixcpp/投稿前チェックリスト - PukiWiki」
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 20:04
by わからんこ
受信内容:
↑何も表示されません。
本来はここに相手のメッセージを表示させたいのですが・・・
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 20:48
by softya(ソフト屋)
わからんこ さんが書きました:受信内容:
↑何も表示されません。
本来はここに相手のメッセージを表示させたいのですが・・・
デバッガでの動作確認はされていないのでしょうか?
必要だから聞いていますので必ずお答え下さい。
あとクライアントで送信していることは確認されていますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 21:48
by わからんこ
本格的にプログラムを書いたことがないので
デバッガでの動作確認と言われても、どうすればよいかわかりません。
デバッガでの動作確認とはなんでもいいのでデバッガをダウンロードしてきて使うのか
それとも、こういったプログラムに適したデバッガがあるのでしょうか?
すいません。まだプログラムに触れて日が浅いので、初歩的な事で詰まってしまいまして・・・
クライアント側は確かに送信しています。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 21:54
by softya(ソフト屋)
わからんこ さんが書きました:本格的にプログラムを書いたことがないので
デバッガでの動作確認と言われても、どうすればよいかわかりません。
デバッガでの動作確認とはなんでもいいのでデバッガをダウンロードしてきて使うのか
それとも、こういったプログラムに適したデバッガがあるのでしょうか?
すいません。まだプログラムに触れて日が浅いので、初歩的な事で詰まってしまいまして・・・
クライアント側は確かに送信しています。
分からないでも良いので、やったか?やれなかったのか?の情報が欲しいわけです。
スルーされるのが一番問題で原因の追求を難しくします。
VisualC++であればデバッガ付属していますが開発環境に何をお使いですか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 23:14
by わからんこ
VisualC++2010 でやっています。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月28日(土) 23:22
by softya(ソフト屋)
VisualC++2010であれば次のように使います。
「プログラムのデバッグ実行」
http://cvwww.ee.ous.ac.jp/vc10prog.html#7
プログラムを通っているポイントと変数の変化をチェックできるので、受信している部分とか受信ハンドルを確認して下さい。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月29日(日) 03:30
by わからんこ
見よう見まねですが、
送信部分にブレークポイントをおき、変数の変化を見てみたのですが
クライアント側は確かに送信できていると思いますが、
受信側のStrBuf(相手の送信内容を受け取る配列)の中身には
相手が送ったものでなく、よくわからない記号た、アルファベットが入っています。
今、プログラムにその様な文字列が表示されることはありません
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月29日(日) 10:38
by softya(ソフト屋)
通信系は初心者が・・・とか言っている場合ではなくて中級者のプログラミング技術を身に着けていかないと作ることができません。
WireSharkもデバッガもちゃんと使いこなさないとバグが取れないので頑張ってください。
わからんこ さんが書きました:送信部分にブレークポイントをおき、変数の変化を見てみたのですが
クライアント側は確かに送信できていると思いますが、
名前以外の送信処理は行われていると言うことですね?
わからんこ さんが書きました:受信側のStrBuf(相手の送信内容を受け取る配列)の中身には
相手が送ったものでなく、よくわからない記号た、アルファベットが入っています。
今、プログラムにその様な文字列が表示されることはありません
ハンドルは確認してもらいましたか?
それとStrBufの状態は何処で確認しましたか?
NetWorkRecv( NetHandle
, StrBuf , DataLength );// データをバッファに取得
この行の次の行にF10で進めないとNetWorkRecvは行われていませんのでStrBufにも値が入りません。
DataLengthにもちゃんと送信したサイズは入っていますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月31日(火) 03:43
by わからんこ
ブレークポイントをつくり、配列に入る数字や文字、パケットなど色々調べました。
結果、受け取りの仕組みを変えたところ、うまくいくようになりました。
折角うまくいったのに、クライアント側のコードをコンパイルした時に、プログラムが実行されなくなりました。
「プログラム '[4496] Client.exe: ネイティブ' はコード 255 (0xff) で終了しました。」と表示だけされます。
これはコンパイルは通っているけど、VisualC++2010で実行されなくなっただけなのか、
プログラムに不具合があって実行されていないのかどちらなのでしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年7月31日(火) 09:13
by softya(ソフト屋)
わからんこ さんが書きました:ブレークポイントをつくり、配列に入る数字や文字、パケットなど色々調べました。
結果、受け取りの仕組みを変えたところ、うまくいくようになりました。
折角うまくいったのに、クライアント側のコードをコンパイルした時に、プログラムが実行されなくなりました。
「プログラム '[4496] Client.exe: ネイティブ' はコード 255 (0xff) で終了しました。」と表示だけされます。
これはコンパイルは通っているけど、VisualC++2010で実行されなくなっただけなのか、
プログラムに不具合があって実行されていないのかどちらなのでしょうか?
プログラムが不具合があって実行されないって事でしょう。
デバッガの出番です。デバッグ開始で異常なポイントで処理が止まりませんか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月01日(水) 00:21
by わからんこ
すこしずつしか前進していませんが、すこし形になってきました。
今のところ、
サーバー側
相手のIP表示と名前、相手が一番最近入力したメッセージを表示
名前とメッセージを接続している全員に送信
クライアント側
文字入力と受信
他の接続者のメッセージを受信
とすこしリファレンスのプログラムより前進した気がします
しかし、まだダメな事もありますので、まだもうちょっとがんばります
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月07日(火) 14:28
by わからんこ
テストが終わったので、再び発展を目指そうとしています、
今までは文字列だけ送信していましたが、もっと複数のデータをやり取りできるように
しようと思いました。
そこで、構造体をつくり、送信し、構造体を受信させようと考えましたが
構造体で一度にたくさんのデータを送るのと、データを複数回に分けて送るのではどちらのほうが
効率が良いのでしょうか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月07日(火) 14:37
by softya(ソフト屋)
要求されるレスポンスタイム(応答時間)やゲーム内容や自分の技量で決めるべきです。
大量のデータを送信するならマトめてのほうが無駄がないでしょうが、それなりに時間がかかります。
分割で送って問題ないように組んだほうがレスポンスタイムは良くなりますがプログラムが複雑になるかも知れません。
つまり、最適の着地点というのは最初に書いた条件のミックスで決まるものですから常に正解の万能解はありません。
実験して経験則で決めたほうが良いとも言えます。
あとなるべく接続するであろう中でも速度の遅い回線の事を意識しないとオンラインゲームは成り立たなくなります。
【補足】
大事なことを忘れていました。
うまく動いたコードを貼り付けていただくようにお願いします。ここのルールとなっております。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月07日(火) 14:52
by h2so5
アプリケーション側でデータを小分けにしても、
TCPレイヤーで自動的にまとめて送信されてしまい意味がない場合もあると思います。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月07日(火) 17:24
by わからんこ
勉強の為に、
http://dixq.net/forum/viewtopic.php?f=3&t=10029 このトピックを元に自分なりに
発展を目指しました。
発展元
http://homepage2.nifty.com/natupaji/DxL ... m.html#N21
一応うまく動きましたが、まだなにかダメなとこがあるかも知れませんがご容赦を
発展元のプログラムを受信側と送信側に分割して作りました。
送信側はあまり変えていませんが、受信側は複数が接続できるような動きを目指して変えました。
コード:
#include "GV.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
//-------------最初の設定--------------//
SetDrawScreen( DX_SCREEN_BACK );
ChangeWindowMode(TRUE);
SetMainWindowText( "サーバー" ) ;
SetAlwaysRunFlag(TRUE);
if( DxLib_Init() == -1 )return -1;// エラーが起きたら直ちに終了
//-------------------------------------//
//-------------変数----------------//
int NetHandle[MAX_CONNECT_NUM],LostHandle[MAX_CONNECT_NUM]; // ネットワークハンドル
int DataLength[MAX_CONNECT_NUM] ;// 受信データ量保存用変数
int NameLength[MAX_CONNECT_NUM] ;// 受信データ量保存用変数
int SendLength[MAX_CONNECT_NUM] ;// 受信データ量保存用変数
IPDATA Ip[MAX_CONNECT_NUM];// 接続先IPアドレスデータ
int Num,Flag,PortNum;
int count[MAX_CONNECT_NUM];
char Name[MAX_CONNECT_NUM][21];
char StrBuf[MAX_CONNECT_NUM][ 41 ];// データバッファ
//送信用
char StrBuf2[MAX_CONNECT_NUM][ 61 ];// データバッファ
int Check[MAX_CONNECT_NUM];
//----------------------------------//
//---------------関数---------------//
int Net_Init(void);
//----------------------------------//
// 接続してくるのを待つ状態にする
PreparationListenNetWork( PortNum=Net_Init() ) ;
//初期化
for(int i=0;i<MAX_CONNECT_NUM;i++){
//strcpy( StrBuf[i], "未受信" ) ;
strcpy( Name[i], "名前未受信" ) ;
NetHandle[i] = -1 ;
count[i]=0;
Check[i]=1;
}
//ESCキーが押されるまでループ
while( ScreenFlip()==0&&ProcessMessage()==0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0&&ClearDrawScreen()==0)
{
//開放中のポート番号表示
DrawFormatString( 0, FONT_SIZE*2 ,GetColor(255,255,255),"現在開放中ポート番号 %d 番",PortNum);
//接続が切れてるかチェック
for(int i=0;i<MAX_CONNECT_NUM;i++){
LostHandle[i]=GetLostNetWork();
if(LostHandle[i]==NetHandle[i]){
strcpy( Name[i], "名前未受信" ) ;
strcpy( StrBuf[i], "" ) ;
NetHandle[i]=-1;
count[i]=0;
}
}
//配列番号を決める
for(int i=0;i<MAX_CONNECT_NUM;i++){
if(NetHandle[i]==-1){
Num=i;
Flag=0;
break;
}else{
Flag=1;
}
}
//接続人数限界以上じゃなかったらつなげる
if(Flag != 1)
NetHandle[Num] = GetNewAcceptNetWork();
//ip保存
GetNetWorkIP(NetHandle[Num] , &Ip[Num]) ;
//接続者の名前を表示
for(int i=0;i<MAX_CONNECT_NUM;i++){
//データを受信してる
if( GetNetWorkDataLength( NetHandle[i] ) != -1 &&GetNetWorkDataLength( NetHandle[i])> sizeof( int )){
if(count[i]==0){
NameLength[i] = GetNetWorkDataLength( NetHandle[i] ) ; // データの量を取得
NetWorkRecv( NetHandle[i] , Name[i] , NameLength[i] );// データをバッファに取得
count[i]=1;
}else{
// データ受信
DataLength[i] = GetNetWorkDataLength( NetHandle[i] ) ; // データの量を取得
NetWorkRecv( NetHandle[i] , StrBuf[i] , DataLength[i] );// データをバッファに取得
int k;
for(k=0;k<MAX_CONNECT_NUM;k++){
if(i!=k)
Check[k]=0;
else
Check[k]=1;
}
}
}
if(NetHandle[i]!=-1){
// 受信したデータを描画
int tmp=0;
if(i==1)tmp=1;
else tmp=0;
DrawFormatString( 0, 50+(FONT_SIZE* ((i*i)+tmp) ),GetColor( 255 , 255 , 255 ), "No %d :接続中 IP:%d.%d.%d.%d 名前:%s サイズ:%d "
,i,Ip[i].d1,Ip[i].d2,Ip[i].d3,Ip[i].d4 ,Name[i],NameLength[i]) ;
DrawFormatString( 0, 50+(FONT_SIZE* ((i*i)+1+tmp) ),GetColor( 255 , 255 , 255 ), "受信内容:%s サイズ %d",StrBuf[i],DataLength[i]);
//---送信配列準備場所---//
strcpy(StrBuf2[i],Name[i]);
strcat(StrBuf2[i], " : ");
strcat(StrBuf2[i],StrBuf[i]);
SendLength[i] = lstrlen(StrBuf2[i]) + 6 ;
//----------------------//
}
// 受信成功のデータを送信
for(int j=0;j<MAX_CONNECT_NUM;j++){
if(i!=j && NetHandle[j]!=-1 && DataLength[i]>0 && Check[j]!=1){
NetWorkSend( NetHandle[j],StrBuf2[i],SendLength[i]);
Check[j]=1;
} }
}
}
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}
//ポート入力を行う
int Net_Init(void){
int Color=GetColor(255,255,255);
int PortNum=0;
// 入力領域と文字出力領域との境界線を引く
DrawLine( 0 , CHAT_LINENUM * FONT_SIZE , 640 , CHAT_LINENUM * FONT_SIZE , Color ) ;
DrawString( 0, 0 ,"接続受付中", Color ) ;
DrawString( 0, FONT_SIZE ,"現在開放しているポート番号を入力して下さい。", Color ) ;
PortNum=KeyInputNumber( 0, (CHAT_LINENUM * FONT_SIZE)+FONT_SIZE, 65535 , 0 ,FALSE) ;
return PortNum;
}
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月07日(火) 19:17
by わからんこ
h2so5 さんが書きました:アプリケーション側でデータを小分けにしても、
TCPレイヤーで自動的にまとめて送信されてしまい意味がない場合もあると思います。
そうなんですか、ではまとめて送るプログラムをとりあえず考えて見ます。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月13日(月) 16:01
by わからんこ
色々考えて、ゴチャゴチャになったので、紙の上で構造を書き出しているのですが、
構造体を送ると際は、サーバー側のプログラムにも、
その構造体を定義しておく必要がありますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月13日(月) 16:13
by softya(ソフト屋)
わからんこ さんが書きました:色々考えて、ゴチャゴチャになったので、紙の上で構造を書き出しているのですが、
構造体を送ると際は、サーバー側のプログラムにも、
その構造体を定義しておく必要がありますか?
中身を触らずに何処かへ投げるだけならサイズだけわかっていれば良いです。
※ クライアント→サーバー→クライアントと言うようにサーバーを経由するだけの場合。
サーバーが中身を参照・変更するなら構造体の定義は必要です。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月13日(月) 16:24
by わからんこ
サーバー経由させる際、受信して
送信するまではどこに一時保管しておけばいいのですか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月13日(月) 16:27
by softya(ソフト屋)
わからんこ さんが書きました:サーバー経由させる際、受信して
送信するまではどこに一時保管しておけばいいのですか?
リングバッファを用意するか、その都度malloc(C++ならnew)して管理するのが一般的です。
まぁ、宛先も管理する必要があるのでリングバッファ・キューの類は必須でしょう。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月14日(火) 01:54
by わからんこ
リングバッファ・キューを行うには、
待ち行列を勉強してきたらいいですか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月14日(火) 07:22
by beatle
C++の標準ライブラリを使っていいなら deque がリングバッファ(キューの実装のやり方の一つ)になっております。
C++編(標準ライブラリ) 第4章 deque
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月14日(火) 10:46
by softya(ソフト屋)
わからんこ さんが書きました:リングバッファ・キューを行うには、
待ち行列を勉強してきたらいいですか?
C言語 リングバッファ
C言語 キュー
C言語 FIFO
で検索すれば色々出てきますよ。
基本的なアルゴリズムですから覚えておいて損はないですし今回は必要だと思います。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月15日(水) 00:31
by わからんこ
FIFOとかは最近勉強したのでわかりますが、
残りはわからないので勉強してきます
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 01:03
by わからんこ
intの変数が5個
floatの変数が5個
charで要素数21の配列ひとつ
この構造体は配列で4つあるとして
いっぺんに送るのは多いですか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 02:11
by h2so5
それは質問になっていないような気がします。
例えば、「3,000円は高いですか?」とだけ聞かれても答えようがないのと同じです。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 10:39
by softya(ソフト屋)
わからんこ さんが書きました:intの変数が5個
floatの変数が5個
charで要素数21の配列ひとつ
この構造体は配列で4つあるとして
いっぺんに送るのは多いですか?
1)合計するとそれは何バイトになりますか?(当然把握しているべきです)
2)そして、そのサイズを大きいと思いますか?
3)あとバイナリデータファイルを扱うことに慣れていますか?
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 13:42
by わからんこ
368バイトあるのですが
個人的には小さいかなと、
質問が漠然としすぎてすいません。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 13:48
by softya(ソフト屋)
わからんこ さんが書きました:368バイトあるのですが
個人的には小さいかなと、
質問が漠然としすぎてすいません。
私も小さいと思います。
それと
intの変数が5個
floatの変数が5個
charで要素数21の配列ひとつ
が4つだと368は計算が合いません。
そういう意味で
3)あとバイナリデータファイルを扱うことに慣れていますか?
が不安です。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 14:57
by わからんこ
すいません。
VECTOR型2つ書き忘れていました。
バイナリデータファイルの扱いはしたことがありません。
Re: DxLibリファレンスの通信のプログラムを発展させたい
Posted: 2012年8月28日(火) 15:32
by softya(ソフト屋)
それでも計算が合わないので、こういう知識がないと危ういということです。
「データ型のアラインメントとは何か,なぜ必要なのか?」
http://www5d.biglobe.ne.jp/~noocyte/Pro ... nment.html
こういうことがバイナリの知識ってことですね。
データサイズについてはダミーを付けてでも増やしてください。
そうしないと思ったタイミングで送信されない可能性があります。