スレッドプログラミングについて – プログラミング – Home

スレッドプログラミングについて
 
通知
すべてクリア

[解決済] スレッドプログラミングについて


okuyama
 okuyama
(@okuyama)
ゲスト
結合: 22年前
投稿: 3
Topic starter  

奥山と申します。

#他のBBSでも書いたのですが、レスがないためこちらでまた質問させて頂きます。

現在、VC++6.0にてスレッドを使用したソケット送受信のプログラムを
作っております。
クライアントは、Windows2000 Pro、サーバは、Solaris8です。

下記のような関係で、それぞれ32~250バイト程度のデータを送受信します。
サーバ <-> 本プログラム <->同一クライアントのメインプロセス

下記ソース中の
SvThreadは、サーバからの受信とメインプロセスへの送信
ClThreadは、メインプロセスからの受信とサーバからの送信
を行っています。

サーバからwriteで、ソケットへの書き込みがあり、selectが受信し、
サーバ側スレッド(SvThread)が生成されます。
このとき、サーバからは規定バイト数(例えば100バイト)送信され、
SvThreadのrecvで100バイト受信しているのですが、なぜか複数のスレッドが
生成されてしまいます。(2個の時もあれば、200個の時もある)

私の予想では、SvThreadにて、recvを行っている間(受信し終わっていない
状態で)にselectが、対象ソケットをチェックしてしまいselectを抜けてしまうの
ではないかと思っているのですが・・・。

この場合、一回のサーバからの送信に対しそれを読み終えるまで
selectが反応しない方法はありませんでしょうか?
ご教授をお願いいたします。

~~~~~ソース~~~~~

int hogehoge(void){

int iRet;
THR_INF ThreadInf;
LPTHRINF lpThreadInf = NULL;
HANDLE hHdl;
HANDLE hEvent[2];
long lThreadId;
unsigned ThreadAddr;
unsigned long ulRet;

// ・・・・・・・・・・・・・・・・・・・
// ソケット作成やら、bindやら、listenやら
// ・・・・・・・・・・・・・・・・・・・

while(1){
//! FD_SET構造体にサーバ側とメイン側のソケット設定
fd_set FdSet;
FD_ZERO(&FdSet);
FD_SET(ServerFD, &FdSet); // ServerFDはグローバル
FD_SET(ClientFD, &FdSet); // ClientFDはグローバル

// 2つのソケットで受信を待ちつづける
iRet = select(FD_SETSIZE, &FdSet, NULL, NULL, NULL);
if (iRet <= 0){
// エラー処理
return(0);
}

// サーバーFDチェック
if (FD_ISSET(ServerFD, &FdSet) != 0){
FD_CLR( ServerFD, &FdSet );
// スレッド生成
lThreadId = _beginthreadex(0, 0, SvThread, lpThreadInf, 0, &ThreadAddr);
if (lThreadId == 0){
//エラー処理
return(1);
}
}else{
// ghMainEventはグローバル
ghMainEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
FD_CLR( ClientFD, &FdSet );
lThreadId = _beginthreadex(0, 0, ClThread, lpThreadInf, 0, &ThreadAddr);
if (lThreadId == 0){
// エラー処理
return(1);
}
}
}
return(0);
}

以上、よろしくお願いいたします。


引用未解決
トピックタグ
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

selectをスレッド側で行えばよいのでは?


返信引用
ボコノン教徒
 ボコノン教徒
(@ボコノン教徒)
ゲスト
結合: 23年前
投稿: 90
 

> 私の予想では、SvThreadにて、recvを行っている間(受信し終わっていない
> 状態で)にselectが、対象ソケットをチェックしてしまいselectを抜けてしまうの
> ではないかと思っているのですが・・・。

で正しいと思います。ソケットの読み込みバッファにデータが残っている限り、
selectが反応するのでしょう。

> この場合、一回のサーバからの送信に対しそれを読み終えるまで
> selectが反応しない方法はありませんでしょうか?

スレッドが1つしか起動できないようにロックするしかないのでは。

ところで

> iRet = select(FD_SETSIZE, &FdSet, NULL, NULL, NULL);

タイムアウトもエラーイベントも設定して無いようですが、これで
大丈夫ですか?


返信引用
okuyama
 okuyama
(@okuyama)
ゲスト
結合: 22年前
投稿: 3
Topic starter  

dairygoods様、ボコノン教徒様、ご返答ありがとうございます。

>> この場合、一回のサーバからの送信に対しそれを読み終えるまで
>> selectが反応しない方法はありませんでしょうか?
>スレッドが1つしか起動できないようにロックするしかないのでは。

このスレッドの起動の制御というのは、どのようにすればできるのでしょうか?

>> iRet = select(FD_SETSIZE, &FdSet, NULL, NULL, NULL);
>タイムアウトもエラーイベントも設定して無いようですが、これで
>大丈夫ですか?

すいません。この辺はこれから勉強します。


返信引用
ボコノン教徒
 ボコノン教徒
(@ボコノン教徒)
ゲスト
結合: 23年前
投稿: 90
 

> このスレッドの起動の制御というのは、どのようにすればできるのでしょうか?

セマフォ(CreateSemaphore(),)とか。


返信引用
okuyama
 okuyama
(@okuyama)
ゲスト
結合: 22年前
投稿: 3
Topic starter  

ボコノン教徒様ありがとうございました。

結局のところ、セマフォ、ミューテックスにての起動の制御の仕方が分からず、
今回はWaitForSingleObjectでスレッド終了を待つことにしました。

ちなみにselectのタイムアウトはhogehogeもスレッドとなっており、
その呼び出し側でタイムアウトを取ってるため不要ということになりました。

ありがとうございました。


返信引用
ボコノン教徒
 ボコノン教徒
(@ボコノン教徒)
ゲスト
結合: 23年前
投稿: 90
 

> ちなみにselectのタイムアウトはhogehogeもスレッドとなっており、
> その呼び出し側でタイムアウトを取ってるため不要ということになりました。

タイムアウトしたらスレッドhogehogeをKILLしちゃう、ということですよね。
selectを抜けた瞬間にKILLされちゃったりするとか、色々問題を残しそうです。
”潜在的バグ”になっちゃいそうな気がします。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

>今回はWaitForSingleObjectでスレッド終了を待つことにしました。

スレッドを起動して、スレッドの終了を待つのであれば、
別スレッドで処理する意味は無いと思いますが。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました