Re: 通信関係の関数でフリーズする ( No.1 ) |
- 名前:管理人 日時:2014/08/30 14:30
> デバッグして詳しく調べたところ、ConnectNetWorkの中に入り、NS_ConnectNetWorkで出てきませんでした。
> しかしNS_ConnectNetWork関数の中でブレークポイントに引っかかることはありませんでした。
ConnectNetWork の中に入って NS_ConnectNetWork に入ったことが分かっているということは
ConnectNetWork の中にブレークポイントを置いたということでしょうか?
NS_ConnectNetWork が呼ばれるところで F11 キーでステップ実行( 関数があったら中に入る )をすれば
NS_ConnectNetWork の中にそのままブレーク状態で追うことができますが、その場合どのようになりますでしょうか?
|
Re: 通信関係の関数でフリーズする ( No.2 ) |
- 名前:だんごさん 日時:2014/08/30 14:47
F11キーをやってみました。
初期化やエラーログなどの関数を巡り巡った後、
extern void _MEMSET( void *Memory, unsigned char Char, size_t Size )という関数の
#ifndef DX_NON_INLINE_ASM
DWORD s = (DWORD)Size ;
DWORD DwordChar = (DWORD)Char ;
__asm
{
CLD
MOV EAX, DwordChar
MOV ECX, s
MOV EDI, Memory
REP STOSB //☆
}
#else...
☆の位置で先に進まなくなりました。
その時の引数の値は、
*Memory: 0x009af0a8
Char : 0
Size : 368
です。
呼び出し履歴は以下の通りです。
soft.exe!DxLib::_MEMSET(void * Memory, unsigned char Char, unsigned int Size) 行 434 C++
soft.exe!DxLib::InitializeHandleManage(int HandleType, int OneSize, int MaxNum, int (DxLib::HANDLEINFO *)* InitializeFunction, int (DxLib::HANDLEINFO *)* TerminateFunction, const char * Name) 行 69 + 0x10 バイト C++
soft.exe!DxLib::InitializeNetWork(HWND__ * WindowHandle) 行 261 + 0x20 バイト C++
soft.exe!DxLib::ConnectNetWorkBase_UseGParam(DxLib::CONNECTNETWORK_GPARAM * GParam, DxLib::tagIPDATA * IPData_IPv4, DxLib::tagIPDATA_IPv6 * IPData_IPv6, int Port, int ASync, int ASyncLoadFlag) 行 1056 + 0x10 バイト C++
soft.exe!DxLib::ConnectNetWorkBase(DxLib::tagIPDATA * IPData_IPv4, DxLib::tagIPDATA_IPv6 * IPData_IPv6, int Port, int ASync) 行 1209 + 0x1f バイト C++
soft.exe!DxLib::NS_ConnectNetWork(DxLib::tagIPDATA IPData, int Port) 行 1481 + 0x11 バイト C++
soft.exe!DxLib::ConnectNetWork(DxLib::tagIPDATA IPData, int Port) 行 1883 + 0xd バイト C++
|
Re: 通信関係の関数でフリーズする ( No.3 ) |
- 名前:管理人 日時:2014/08/31 02:54
なんと、意外なところで止まっていますね・・・
アセンブラで記述した箇所が問題になっているみたいですので、DxCompileConfig.h の以下のように記述されている箇所
// インラインアセンブラを使用しないソースコードでコンパイルする場合は以下のコメントアウトを外してください
//#define DX_NON_INLINE_ASM
の、//#define DX_NON_INLINE_ASM ←この部分の//を外して
// インラインアセンブラを使用しないソースコードでコンパイルする場合は以下のコメントアウトを外してください
#define DX_NON_INLINE_ASM
↑のような状態でコンパイルしてみてください
アセンブラを使用しなくなるので、少なくとも REP STOSB の箇所では止まらなくなると思います
|
Re: 通信関係の関数でフリーズする ( No.4 ) |
- 名前:だんごさん 日時:2014/08/31 03:56
「繰り返し処理」を「止まった」と勘違いしていました。アセンブラをなくして
値が見れるようになったことにより気付きました。申し訳ありません。
さて、新たに止まった場所が分かりましたので報告いたします。
extern int InitializeNetWork( HWND WindowHandle )関数の
SockData.MessageWindow =
CreateWindowEx(
WS_EX_TRANSPARENT,
Name,
Name ,
( ParentWindow ? WS_CHILD : 0 ) | WS_MINIMIZE,
0, 0, 0, 0,
ParentWindow,
NULL,
hInst,
NULL );
この関数から出てきませんでした。CreateWindowExに渡される引数に目立ったエラー値などはありませんでした。
普通のCreateWindowにして実験してみましたがやはりダメでした。
それにしても、DxLibって内部でこんなウィンドウ作ってたんですね…
|
Re: 通信関係の関数でフリーズする ( No.5 ) |
- 名前:管理人 日時:2014/08/31 11:21
CreateWindowEx から出てこないとなるとかなり異常な状態ですね・・・
これ以上は直接プログラムを手元で実行してみないと追えそうにありません
もし不都合がなければ現象が確認できるプログラムと、プログラムの実行に
必要なファイルをこちら
BQE00322(あっとまーく)nifty.com
( (あっとまーく)を@に置き換えてください )
に送っていただけないでしょうか?
> それにしても、DxLibって内部でこんなウィンドウ作ってたんですね…
はい、通信メッセージを受け取るために作成しています
|
Re: 通信関係の関数でフリーズする ( No.6 ) |
- 名前:管理人 日時:2014/09/01 02:40
メールありがとうございます、手元で現象を確認できました
ConnectNetWork が DxLib_Init を呼んだスレッドとは別のスレッドで実行されているのですね
調べ切れていませんが、初めて通信関係の関数が呼ばれた際に実行している InitializeNetWork が
別スレッドから呼ばれた場合に正常に動作しないようです
と言うより、コンパイルオプションの DX_THREAD_SAFE を有効にして複数スレッドから
同時に呼ばれた場合の対処はしましたが、それでも、以前お話しました通りDXライブラリは
DxLib_Init を呼んだスレッド以外のスレッドからDXライブラリの関数が呼ばれることを前提としていないので、
DxLib_Init を呼んだスレッド以外のスレッドからDXライブラリの関数を呼ぶと今回の件以外にも色々と問題が発生しそうです
とりあえず今回の問題は DxLib_Init の直後に
IPDATA IpBuffer ;
GetMyIPAddress( &IpBuffer ) ;
という記述を増やして、『通信関係の関数が初めて呼ばれた際に実行される InitializeNetWork』を
予め実行するようにすることで ConnectNetWork から出てくるようになりましたので、よろしければお試しください
|
Re: 通信関係の関数でフリーズする ( No.7 ) |
- 名前:だんごさん 日時:2014/09/01 18:35
ありがとうございます。
やはりスレッドが関係していましたか…
色々と問題が発生するとのことですが、実はConnectNetWork関数が接続したにもかかわらず-1を返す
という現象が発生しています…。
サポート対象外だと思いますので質問しづらいのですが…。
少し調べてみたところ、Dxnetwork.cppのConnectNetWorkBase_Static関数
// 同期接続指定の場合はここで接続を一定時間接続を待つ
if( ASync == FALSE )
{
int StTime ;
StTime = NS_GetNowCount() ;
if( SockData.TimeOutWait == 0 ) SockData.TimeOutWait = WSA_TIMEOUTWAIT ;
while( ( ( NS_GetNowCount() - StTime ) < SockData.TimeOutWait ) && ( Sock->ConnectionFlag == FALSE ) )
{
if( NS_ProcessNetMessage() != 0 ) break ;
Sleep( 1 ) ;
}
if( Sock->ConnectionFlag == FALSE )
goto ERR ; // ☆
}
☆の部分でエラーが返されていました。
おそらくProcessNetMessage関数のウィンドウメッセージの処理で何か起きているのではないかと
思うのですが、これをどうにかするのは無理なので、通信用スレッドを作る?などの何かしらの解決方法
を教えてほしいです。
想定外のことを勝手にやって問題が出たので質問するという身勝手なものですが、
どうかお願いできないでしょうか…?
|
Re: 通信関係の関数でフリーズする ( No.8 ) |
- 名前:だんごさん(解決) 日時:2014/09/02 02:03
すみません、非同期接続で接続ができました。
色々とありがとうございました。
|
Re: 通信関係の関数でフリーズする ( No.9 ) |
- 名前:だんごさん 日時:2014/09/02 19:07
何度もすみません。
非同期接続では、接続してもしなくても成功と返ってくるようです…。
同期接続では接続してもしなくても失敗になります…。
|
Re: 通信関係の関数でフリーズする ( No.10 ) |
- 名前:管理人 日時:2014/09/04 00:33
非同期で ConnectNetWork を実行した場合は接続開始処理が失敗しない限り成功として返ってきます
その後実際に接続が確立するかどうかは別途監視する必要があります
ConnectNetWork の非同期接続には SetUseASyncLoadFlag( TRUE ) ; を使用する方法と ConnectNetWork_ASync を
使用する法方と二つあるのですがどちらでしょうか?
< SetUseASyncLoadFlag( TRUE ) ; の場合 >
// 非同期読み込みが完了するまで待つ( メインスレッドで ProcessMessage を定期的に呼んでいるものとします )
int Result = FALSE ;
int StartTime = GetNowCount() ;
while( Result == FALSE )
{
Result = CheckHandleASyncLoad( NetHandle ) ;
Sleep( 1 ) ;
// 何秒でタイムアウトとするかは自分で決めます
if( GetNowCount() - StartTime > 10000 )
{
break ;
}
}
// ハンドルエラーが発生したか、接続していない場合は接続失敗
if( Result >= 0 && GetNetWorkAcceptState( NetHandle ) == TRUE )
{
// 接続成功
}
else
{
// 接続失敗した場合はハンドルは自動的に削除されます
}
< ConnectNetWork_ASync の場合 >
// 接続待ち( メインスレッドで ProcessMessage を定期的に呼んでいるものとします )
int StartTime = GetNowCount() ;
while( GetNetWorkAcceptState( NetHandle ) == FALSE )
{
Sleep( 1 ) ;
// 何秒でタイムアウトとするかは自分で決めます
if( GetNowCount() - StartTime > 10000 )
{
break ;
}
}
// 接続しているかどうかチェック
if( GetNetWorkAcceptState( NetHandle ) == TRUE )
{
// 接続成功
}
else
{
// 接続失敗の場合は自分でハンドルを削除する必要があります
CloseNetWork( NetHandle ) ;
}
よろしければお試しください
|
Re: 通信関係の関数でフリーズする ( No.11 ) |
- 名前:だんごさん 日時:2014/09/05 03:27
説明が悪かったです。すみません。
非同期ではない、ただのConnectNetWorkでは、接続されてもエラーが返ってきてループを抜け出しません。
一方非同期のConnectNetWork_ASyncの方では、たとえ接続していなくともGetNetWorkAcceptStateでも成功と返ってきます。
おそらくこれもマルチスレッドの影響ではないかと思っているのですが…どうにかクリアしたいです。
|
Re: 通信関係の関数でフリーズする ( No.12 ) |
- 名前:管理人 日時:2014/09/07 12:39
> 非同期ではない、ただのConnectNetWorkでは、接続されてもエラーが返ってきてループを抜け出しません。
ConnectNetWork の前に SetUseASyncLoadFlag( TRUE ) ; を実行して、非同期モードの状態で
ConnectNetWork を使用しても ConnectNetWork から出てこないのでしょうか?
|
Re: 通信関係の関数でフリーズする ( No.13 ) |
- 名前:だんごさん 日時:2014/09/07 14:55
SetUseASyncLoadFlag( TRUE ) ;を使用してもまるで非同期のようにしばらく動かない状態になります。
ただし非同期用のコードは通っているようです。
また、戻り値は非同期のハンドルです。
接続関数(ConnectNetWork)に入ると相手側も成功になりますが、
接続関数から出てくると相手側も切断されたと表示されます。
CheckHandleASyncLoadは-1、時々1になったりします。0になることはありません。
|
Re: 通信関係の関数でフリーズする ( No.14 ) |
- 名前:管理人 日時:2014/09/07 17:36
> SetUseASyncLoadFlag( TRUE ) ;を使用してもまるで非同期のようにしばらく動かない状態になります。
『まるで同期のように』の誤りですよね?
ともあれ、それで駄目となりますと後は合わせ技で・・・
SetUseASyncLoadFlag( TRUE ) ; を実行して非同期設定にした上で
ConnectNetWork_ASync を使用して接続するという方法を試してみてください
接続完了チェックのコードも合わさって以下の様になります
// 非同期ハンドル作成処理が完了するまで待つ
// ( メインスレッドで ProcessMessage を定期的に呼んでいるものとします )
int Result = FALSE ;
while( Result == FALSE )
{
Result = CheckHandleASyncLoad( NetHandle ) ;
Sleep( 1 ) ;
}
// ハンドル作成エラーが発生し場合は失敗
if( Result < 0 )
{
// ハンドル作成に失敗した場合はハンドルは自動的に削除されます
}
else
{
// 接続待ち( メインスレッドで ProcessMessage を定期的に呼んでいるものとします )
int StartTime = GetNowCount() ;
while( GetNetWorkAcceptState( NetHandle ) == FALSE )
{
Sleep( 1 ) ;
// 何秒でタイムアウトとするかは自分で決めます
if( GetNowCount() - StartTime > 10000 )
{
break ;
}
}
// 接続しているかどうかチェック
if( GetNetWorkAcceptState( NetHandle ) == TRUE )
{
// 接続成功
}
else
{
// ここで接続失敗の場合は自分でハンドルを削除する必要があります
CloseNetWork( NetHandle ) ;
}
}
|
Re: 通信関係の関数でフリーズする ( No.15 ) |
- 名前:だんごさん(解決) 日時:2014/09/07 20:31
できました!!
ただ接続できただけなのですがとても感動しました。
無茶な質問でしたが、解決していただき本当にありがとうございました!
|