Re: チャットプログラムについて ( No.1 ) |
- 名前:Will 日時:2006/12/18 10:14
listen関数で新しい接続を見つけた時に
// 新しい接続があった場合はループを出る
if( NetHandle != -1 ) break ;
としてますが、この時クリティカルセクションを開放していません。
そのため、デッドロックしているものと思います。
|
Re: チャットプログラムについて ( No.2 ) |
- 名前:たけ 日時:2006/12/18 10:49
Willさんお返事ありがとうございます
おっしゃるとおり、そこでデッドロックがかかる可能性がありますね^^;
修正しておきます
しかし、フリーズが起きてるのはその前なんです
listenするスレッドを呼び出すと
まずlistenする旨のメッセージを表示するようになっているのですが
それも表示せずに固まってしまうのです
|
Re: チャットプログラムについて ( No.3 ) |
- 名前:Will 日時:2006/12/18 12:13
直接の原因は見つけられませんが、いくつか気になったところを上げさせていただきます。
@StringYを初期化していない。(グローバル変数だからたぶん0であるとは思いま
すが、0でないとすれば動作は予測不能)
ANetHandle変数に排他アクセスできていない
メインスレッドとlistenスレッドで同時アクセスしているタイミングあります。
メインスレッド:315行目
listenスレッド:249,252行目
そのため、NetHandle変数の更新タイミングによっては予想外の動きをする可能性があります。
BProcessMessageを複数スレッドから同時コールしている
私はこういうことをした経験がないので管理人さんに聞かないとわかりませんが、
ProcessMessageを同時コールしてもよかったのでしょうか?
CScreenStringAdd関数は複数スレッドからのコールに対応していない
ソースを見る限りでは同時コールしてないと思いますが、もし同時コールした場合
グローバルエリアを破壊しまくります。
質問
listenスレッドとchatスレッドでクリティカルセクションを使用していますが、
どういった理由で使用されているのでしょうか?
ソース見る限りでは意味が無い様に思います。
|
Re: チャットプログラムについて ( No.4 ) |
- 名前:たけ 日時:2006/12/18 12:40
なるほど、ためになります
Aについてはバイパスするためにつけました
チャットがうまく作動すればここからゲーム処理をしようと思っていましたが
説明不足ですいません
B、Cについては全く知りませんでした
同時コールについてもう少し詳しく調べてみたいと思います
質問の回答
今回は1対1のチャットプログラムにおいて
スレッドが上手く作動するか調べてみたものです
もしうまくいけば複数とのチャットにするべく
listenを別スレッドにして複数アクセスができるようにしたかったのです
実はこちらにおいてあるチャットサンプルを見て
すぐ複数のチャットの作成にとりかかったのですが上手くいかず
スレッドが上手く作動していないという結論にいたり
投稿させていただいたものです
別プログラムでスレッドを作動させた場合は上手く動いたので
このように組み合わせると良くないのでは?と思いました
とにかく、Willさんにはご迷惑をおかけしました
回答して頂きましたことに感謝いたします
|
Re: チャットプログラムについて ( No.5 ) |
- 名前:Will 日時:2006/12/18 13:14
>とにかく、Willさんにはご迷惑をおかけしました
ぜんぜん迷惑ではないですよ。
いろいろな質問に答えることで、私自身も勉強になりますのでお気になさらず質問してください。
余談ですが、マルチスレッドプログラミングをする場合の注意点をいくつか
1.各スレッド間で共有する変数は使用しない
変数は複数のタスクから同時にアクセス(参照・更新)するとデータが壊れます。
2.各スレッド間で共有する関数にはStatic変数、グローバル変数を使用しない
上記と同じ理由から。
ローカル変数の場合は、関数コールごとに作成されるので問題ない。
Static変数、グローバル変数を使用した関数を共有したい場合は、クリティカルセクションを使用して関数が同時実行しないようにする。
例:
void func(void)
{
クリティカルセクション獲得(2番目以降にこの関数をコールしたスレッドはここから先に進まない)
処理
クリティカルセクション開放
}
※DXライブラリ付属の関数は排他制御されてるはず。
3.各スレッド間でのデータの受け渡しを行う変数は、バイナリセマフォを使用して排他アクセスにする。
変数に対する同時アクセスをなくして、データ破壊を防ぐ。
以上です。
参考にしてください。
|
Re: チャットプログラムについて ( No.6 ) |
- 名前:たけ 日時:2006/12/18 16:24
Willさん、丁寧に解説ありがとうございます
このようにプログラムを変えてみたところ上手くいきました
ttp://www.geocities.jp/syasinwomisetaiyo/ChatProgramDx02.txt
改正したものとしては
・指摘のあったメインスレッドの排他アクセスできていない箇所の修正
・サブスレッド内のwhile関数の終了フラグを作りメインスレッドから
サブスレッドのwhile関数終了を呼び出す
・PreparationListenNetWork関数をメインスレッドから呼び出す
・その他メインスレッドからESCボタンで終了できるようにする
です
問題はスレッドからlisten関数、
つまりPreparationListenNetWork関数を用いたことだと思います
勝手な推測ではありますが、Willさんの解説を元に考えると
この関数が使う処理で低レベルなところで同時コールがあったのでは、と思いました
上のプログラムでもまだまだ何か危ない匂いはしますが
とりあえず機能しているので安心しました
Willさんどうもありがとうございました
|
Re: チャットプログラムについて ( No.7 ) |
- 名前:たけ 日時:2006/12/18 17:45
追記です
この件についてなんですが
同時コールによるグローバル変数の破壊ではない気がしてきました
おそらくサブスレッドである特定のDXライブラリ関数を用いると
宣言されていない変数や関数が発生するためなのではないかと考えられます
これは
PreparationListenNetWork() //フリーズしてしまう
MakeKeyInput() //入力方法が変えられない
で確認できました
メインスレッドではおそらくDxLib_Init関数で宣言してるため
こちらで上記の関数を用いても不具合は起こりませんが
サブスレッドで使用するとおかしなことが起こります
上記の関数をサブスレッドで使用したい場合は
どのような処理が必要なのでしょうか?
|
Re: チャットプログラムについて ( No.8 ) |
- 名前:Will 日時:2006/12/19 11:06
>宣言されていない変数や関数が発生するためなのではないかと考えられます
DXライブラリもC言語できていますので、宣言されていない変数や関数が突然発生することはありません。そもそもきちんと宣言していないとコンパイルが通りません。
(私が理解したものと違う意味だったらごめんなさい)
PreparationListenNetWorkですが、1回目にコールした時にフリーズしますか?2回目以降ですか?
といいますのは、DXLibのソースを見たところネットワーク関係の関数を最初にコールした時に、ネットワーク初期化関数(InitializeNetWork)を内部的にコールしています。
そのため、複数のスレッドからネットワーク関連関数をコールした時に初期化関数内で何かあるのかもしれません。
すいませんが、PreparationListenNetWorkでフリーズした時のDXライブラリのログ(Applog.txtだったかな?)の内容を貼り付けてもらえないでしょうか。
|
Re: チャットプログラムについて ( No.9 ) |
- 名前:たけ 日時:2006/12/19 12:11
Willさん
>そもそもきちんと宣言していないとコンパイルが通りません。
そうですよね、根本的なことを見逃していました・・・
メインスレッドでやっていてサブスレッドでやっていないこと〜
って考えるとこれはDxLib_Initかなぁと思ったりしまして
ところで今はなぜか色々いじっているとちゃんと動くようになりまして
自分でも何が悪かったのかわかっていません
・なるべく同時コールが起こらないように
・接続のないネットハンドル配列は使わないように
(複数の相手に接続するのに変数で制御しているため)
というのを重点的に修正しました
やはりこのあたりがあやしかったんではないでしょうか
なのでフリーズは今現在は起こらないのですが
トピックに載せてあるプログラムを作動させて
そのログを渡せばよろしいでしょうか?
|
Re: チャットプログラムについて ( No.10 ) |
- 名前:Will 日時:2006/12/19 12:29
問題が起こっていないのであれば結構です。
また発生した時でもかまいません。
|
Re: チャットプログラムについて ( No.11 ) |
- 名前:たけ 日時:2006/12/19 12:51
Willさん
お手数かけてすみません
本当にありがとうございました
|
Re: チャットプログラムについて ( No.12 ) |
- 名前:たけ 日時:2007/01/09 17:16
おひさしぶりです。
上記のチャットプログラムでの質問です。
一応ゲームプログラム全体としてまとまってきたので
テストプレイを行おうとしたところ、
接続する場合にIPアドレスを入力しても'.'の数を
かぞえてくれないマシンがありました。
自分のPCではちゃんと入力したIPをバッファに入れてくれるので
プログラム自体にミスはないと思うのですが
この場合、他に処理を加える、
もしくは何かPC側で何か設定を変えなければいけないのでしょうか?
ちなみにIP入力のプログラムは全く上記のものと同じで、
動作させたPCは自分のものも含めてすべてXP SP2でした。
|
Re: チャットプログラムについて ( No.13 ) |
- 名前:たけ 日時:2007/01/09 17:21
少しわかりにくいかと思ったので補足です。
IPアドレス入力
↓
'.'が3つあるか確認 → なければ入力にもどる
↓
IPDATAにそれぞれの値を代入
↓
他のマシンに接続
というアルゴリズムなんですが
ここで'.'を3つ入れていても'.'が3つではないと返され、
入力に戻ってしまうPCがあるんです。
文字コードとかの問題なのでしょうか・・・?
|
Re: チャットプログラムについて ( No.14 ) |
- 名前:Will 日時:2007/01/09 22:58
>'.'が3つあるか確認 → なければ入力にもどる
差支えがなければこの部分のソースを貼ってもらえないでしょうか。
|
Re: チャットプログラムについて ( No.15 ) |
- 名前:たけ 日時:2007/01/09 23:53
Willさんおひさしぶりです
ソースは最初に貼ってあるものとかわりませんが、
特にそこの部分だけをピックアップしたものを再度貼らせていただきます
ttp://www.geocities.jp/syasinwomisetaiyo/example.txt
|
Re: チャットプログラムについて ( No.16 ) |
- 名前:たけ 日時:2007/01/10 00:14
すいません、自己解決致しました。
これはバッファが初期化されていないことによるものでした。
おそらく宣言した時点でPCによっては'.'が入っていたのではないかと思います。
|