64ビット用プロセスでselect()できない – プログラミング – Home

64ビット用プロセスでselect()...
 
通知
すべてクリア

[解決済] 64ビット用プロセスでselect()できない


あゆしお
 あゆしお
(@あゆしお)
ゲスト
結合: 14年前
投稿: 11
Topic starter  

こんにちは。
安易な質問かもしれませんが、ご教授ください。

-【環境】---------------------------------
OS : Windows Server 2008
ソフト : Visual Studio 2008 (VC++)
------------------------------------------

64ビット用のプロセスでSocket通信を作成しています。
select()でタイムアウト時間を指定して、
accept()で接続確認する箇所があるのですが、

select()の戻り値が-1となり、タイムアウト時間が有効にならず
accept()でブロック状態になってしまいます。

32ビット用のプロセスで動作すると、正常にタイムアウト時間まで
accept()を行い終了します。

64ビット用でselect()は使えないのでしょうか?
select()に代わるモノが64ビット用に存在するのでしょうか?
宜しくお願い致します。


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

・selectはx64でもつかえる
・とりあえず、最低限のソースを提示してみて
・x86とx64では変数の定義が変わってたりするので、select時に引数の内容を確認
たとえば、待ち時間指定に、他の変数からtimevalに代入してるなら
その際に値がおかしくなっていないか・・・など

・どういう流れかわからんが、SOCKET_ERRORが返ってきてるのにaccept作業させるのはお
かしいと思う


返信引用
あゆしお
 あゆしお
(@あゆしお)
ゲスト
結合: 14年前
投稿: 11
Topic starter  

ご返信ありがとうございます!

抜粋ですが、ソースを提示します。
---------------------------------------------------------------------------
#include <winsock2.h>

SOCKET m_MySocket; // ソケット
SOCKET m_YourSocket; // ソケット
int SockAddrSize; // ソケットサイズ
fd_set fd;
timeval timeout;
int rtc;

// ■タイムアウト時間設定
FD_ZERO( &fd );
FD_SET( m_MySocket, &fd );
timeout.tv_sec = 0;
timeout.tv_usec = 500; //(500ミリ秒)

// ■select()
rtc = select( 1, &fd, NULL, NULL, &timeout );
(↑timeoutの中身は、tv_sec:0、tv_usec:500)

// ■accept()
SockAddrSize = sizeof( m_SockAddr );
m_YourSocket = accept( m_MySocket,
(struct sockaddr *)&m_SockAddr,
&SockAddrSize );

(…ここ↑でブロックし、以降↓に進まず…)

if( p_Main->m_YourSocket != INVALID_SOCKET ){
// ■データ送信処理

}
---------------------------------------------------------------------------
※select()の戻り値は-1ですが、今のトコロ無条件にaccept()しています。

ご指摘のほど、宜しくお願い致します。


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

見た限りでは問題は見つけられませんでした

selectのあとにWSAGetLastError()で、エラーを確認してみてください。

ソレと・・・ソースにはかかれてないから推測になるのですが
リスンソケットを作成などもエラーチェックなしでしょうか?
その場合、それらが正常に行われているかどうかは確認済みでしょうか?

selectより前の部分のエラーも確認してみてはどうでしょうか


返信引用
あゆしお
 あゆしお
(@あゆしお)
ゲスト
結合: 14年前
投稿: 11
Topic starter  

select()以前のソースも追加して記載致します。

------------------------------------------------------------------------
#include <winsock2.h>

unsigned short port_no = 8001; // ポート番号
int rc; // リターンコード
WSADATA wWsaData; // WinSock情報
SOCKET m_MySocket; // ソケット
SOCKADDR_IN m_SockAddr; // ソケット情報
int SockAddrSize; // ソケットサイズ
fd_set fd;
timeval timeout;
int rtc;

// ①WinSockの初期化
if( WSAStartup( MAKEWORD(2,0), &wWsaData ) != 0 ){
rc = -1;
}

// ②ソケット生成
if( (m_MySocket = socket( PF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET ){
rc = -2;
}

// ③Bind
m_SockAddr.sin_family = PF_INET;
m_SockAddr.sin_port = htons(port_no);
m_SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset( m_SockAddr.sin_zero, 0x00, sizeof(m_SockAddr.sin_zero) );

if( bind( m_MySocket,
(struct sockaddr *)&m_SockAddr,
sizeof(m_SockAddr) ) != 0 ){
rc = -3;
}

// ④Listen
if( listen( m_MySocket, 5 ) != 0 ){
rc = -4;
}

// ■タイムアウト時間設定
FD_ZERO( &fd );
FD_SET( m_MySocket, &fd );
timeout.tv_sec = 0;
timeout.tv_usec = 500; //(500ミリ秒)

// ■select()
rtc = select( 1, &fd, NULL, NULL, &timeout );

// ▲(確認用エラーコード出力)
rtc = WSAGetLastError();

------------------------------------------------------------------------

ソースの①~④までは異常値が返ってこなかったので、
正常に行われていると思います。

また、select()後のWSAGetLastError()は
「10038(ソケット以外のものに対して操作を実行?)」でした。

差し支えなければ、、
select()が正常に動作するソースをご提示いただけないでしょうか(x64用)?


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

> 差し支えなければ、、
> select()が正常に動作するソースをご提示いただけないでしょうか(x64用)?
ソースの提示は出来なくても、何らかのサンプルはあるかと思います。

http://foldingforum.org/viewtopic.php?f=8&t=4187
海外版です

他にも探せばありそうです。


返信引用
通りすがり
 通りすがり
(@通りすがり)
ゲスト
結合: 24年前
投稿: 92
 

> timeout.tv_usec = 500; //(500ミリ秒)

ここマイクロ秒単位じゃなかったっけ?


返信引用
あゆしお
 あゆしお
(@あゆしお)
ゲスト
結合: 14年前
投稿: 11
Topic starter  

ネットからサンプルを探してその通りにやってみましたが、
現象は変わらずです・・・。

いろいろと調査した結果、select()でのタイムアウトは諦め、
WSAAsyncSelect()でaccept()を非ブロック化することにします。
目的はaccept()でブロックしてしまうのを解消したかったので。。

以下、対策したソースです。
-----------------------------------------------------------------------------

(↓この部分を削除)
> FD_ZERO( &fd );
> FD_SET( m_MySocket, &fd );
> timeout.tv_sec = 0;
> timeout.tv_usec = 500; //(500ミリ秒)

> rtc = select( 1, &fd, NULL, NULL, &timeout );
(↓これに変える)
rtc = WSAAsyncSelect( m_MySocket, hWnd, WM_APP, FD_ACCEPT );

-----------------------------------------------------------------------------

何とも腑に落ちませんが、、やりたい事は解決しました。
ご返信していただいた方々ありがとうございました。


返信引用
yoh2
 yoh2
(@yoh2)
ゲスト
結合: 18年前
投稿: 70
 

以下の環境で試してみましたが再現しませんでした。
まあ、OSが違うものですけど。

OS: Windows 7 Ultimate x64
開発ソフト: Visual Studio 2008 & 2010
ビルドターゲット: x86 & x64

> rtc = select( 1, &fd, NULL, NULL, &timeout );

selectの第一引数が怪しいといえば怪しいのですが、MSDNでは無視されるとありますし。
ちなみに、Berkeley Socketでは、ここはfd_setの要素数ではなく、
fd_setに格納されたデスクリプタ(≒ソケット)のうちの最大値 + 1となっています。
# Unixでは、ソケットの型はintなんです。
今回の例なら m_MySocket + 1。

あと、読んでいてちょっと不安になった部分があったため念のため指摘。
誤読だったらごめんなさい。

> select()でタイムアウト時間を指定して、
> accept()で接続確認する箇所があるのですが、
>
> select()の戻り値が-1となり、タイムアウト時間が有効にならず
> accept()でブロック状態になってしまいます。

ここを読む限り、select()はタイムアウト時間を設定するだけで
すぐに戻り、accept()を呼び出し時に接続が来なかった場合、
select()で指定したタイムアウト時間後にaccept()が戻る、と
考えているように思えました。
実際には、タイムアウトまで待つのはselect()の仕事です。
接続があればその場でselect()が返り、接続がなければタイムアウト
時間後にselect()が返ります。
どちらだったのかは戻り値で判定、と。
今回の例では、接続があったなら1、タイムアウトしたら0になります。


返信引用
yoh2
 yoh2
(@yoh2)
ゲスト
結合: 18年前
投稿: 70
 

ありゃ、入れ違い……


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

ざっくりですが
***********************************************************
int SockRet;
fd_set Fds;
struct timeval WaitTime;
sockaddr_in dstAddr;
SOCKET Socket;
WaitTime.tv_sec = 1;
WaitTime.tv_usec = 0;
int dstAddrSize = sizeof(sockaddr_in);

while( WaitForSingleObject( *KillEvent , 0 ) == WAIT_TIMEOUT){

FD_ZERO( &Fds );
FD_SET( LisnSocket, &Fds );
SockRet = ::select( NULL , &Fds, (fd_set *)NULL, (fd_set *)NULL,
&WaitTime);
FD_CLR( LisnSocket, &Fds );

if (SockRet == 0){
continue;
}

if( SockRet ==SOCKET_ERROR){
/*エラー処理*/
}

//Accept
Socket= accept(LisnSocket, (struct sockaddr *) &dstAddr,
&dstAddrSize);

/*あと略*/
}
******************************************************
こんなです。

XP、win7かつ、ソリューション構成・OSともにx64で動いています。
開発は2008

64ビットOSでselectが使えないなんてことがあれば、
大きな話題になってると思うのですが
「Windows Server 2008」「x64」「SOCKET」「通信」「select」
といった単語を組み合わせてグーグル検索してみたのですが
似たような現象の話は見つかりませんでした。

で、
すでに32ビットで成功しているソースを使うのではなく
新しくソリューションをつくり、リスンソケット作成からselectするだけのものを作り
実験してみてはいかがでしょうか?


返信引用
yoh2
 yoh2
(@yoh2)
ゲスト
結合: 18年前
投稿: 70
 

Windows Server 2008 x64でも試してみました。
インストール直後の状態(※)と、今日までの
Windows Updateを適用した状態(SP2)の2種類で
試しましたが、どちらもselect()が-1を返すことは
ありませんでした。
参考まで。

※ SPがいくつだったか調べておくのを忘れました。
更新履歴を見る限りSP2より前だとは思います。
7/12にMSDNからダウンロードしたisoイメージで
インストールしたものです。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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