アプリ版:「スタンプのみでお礼する」機能のリリースについて

現在、Winsock2を使ってあるサーバーのプログラムを作成しています。

WSAEventSelect関数を使って非ブロッキングソケットを扱っているのですが、複数のクライアントからほぼ同時に接続要求などがあった際に
接続を取りこぼしてしまいます。

どなたかアドバイスいただけませんでしょうか。

以下、ソースを示します。プログラムの動作をわかりやすくするためエラー処理などは省略して記載します。(実際には行っています)

ちなみに非ブロッキングソケットを使用する理由は以下のとおりです。
・GUIアプリのワーカースレッドで動作させており、ブロッキングソケットでブロック中にメインスレッドが終了してもワーカースレッドがそれを知る術がなくワーカースレッドを安全に終了させることができないため。


/* 変数の宣言*/
intiRet=-1;
SOCKETListenSock;
SOCKETAcceptSock;
intiRcvClientLen=0;
intiRcvLen=0;
charcaRcvDat[1024]={0};
WSAEVENThEvent;
DWORDdwResult;
WSANETWORKEVENTSevents;

/* リッスンソケットを作成*/
ListenSock = socket(AF_INET, SOCK_STREAM, 0);

/* イベントのクリエイト*/
hEvent = WSACreateEvent();

/* リッスンソケットの設定*/
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT_NUM);/*PORT_NUMは定数*/
addr.sin_addr.S_un.S_addr = INADDR_ANY;

/* リッスンソケットをバインド*/
iRet = bind(ListenSock, (struct sockaddr *)&addr, sizeof(addr));

/* リッスンソケットでポートを開く*/
iRet = listen(ListenSock, 10);

/* クライアント接続待ちの無限ループ*/
while (1) {
printf("\n\n/--------- 待機中---------/\n\n");
iRcvClientLen = sizeof(client);

/* リッスンソケットにACCEPTイベントを設定*/
iRet = WSAEventSelect(ListenSock, hEvent, FD_ACCEPT);

/* ACCEPTイベント発生まで待機*/
dwResult = WSAWaitForMultipleEvents(1, &hEvent, FALSE, WSA_INFINITE, FALSE);

/* 発生したイベントを解析*/
iRet = WSAEnumNetworkEvents(ListenSock, hEvent, &events);
/* イベント変数をリセット*/
WSAResetEvent(hEvent);

/* 発生したイベントがACCEPTであれば接続を受け入れる*/
if(events.lNetworkEvents & FD_ACCEPT){
AcceptSock = accept(ListenSock, (struct sockaddr *)&client, &iRcvClientLen);
}

/* ACCEPTしたソケットにREADイベントを設定しなおす*/
iRet = WSAEventSelect(AcceptSock, hEvent, FD_READ);

/* READイベント発生まで待機*/
dwResult = WSAWaitForMultipleEvents(1, &hEvent, FALSE, WSA_INFINITE, FALSE);
/* 発生したイベントを解析*/
iRet = WSAEnumNetworkEvents(AcceptSock, hEvent, &events);
/* イベント変数をリセット*/
WSAResetEvent(hEvent);

/* 発生したイベントがREADであればデータを読み込む*/
if(events.lNetworkEvents & FD_READ){
iRcvLen=recv(AcceptSock, caRcvDat, 1024, 0);

/* ・・・以下Recv後の動作・・・*/

}
}

おそらく、2回目のWSAWaitForMultipleEvents関数で待機している間に接続要求が来たクライアントを取りこぼしているのだと思いますが、
対処方法がわかりません。

A 回答 (1件)

WSAEventSelect()使ったことありませんが…


# というかサーバ側プログラム書いたことないですが。

疑問点として…

WSAResetEvent()をsocket関連の関数をコールする前に実施して問題ないのか?
とか…
>/* ACCEPTしたソケットにREADイベントを設定しなおす*/
>iRet = WSAEventSelect(AcceptSock, hEvent, FD_READ);
イベントを「使い回す」のではなく、ListenSock用とAcceptSock用で別々に持ったらどうなのか?
とか…
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています