サーバーには 2 つのスレッドがあり、1 つのワーカー スレッドと 1 つの受信スレッドがあります。このサーバーのすべてのアクティブなクライアントのリストを含む共有キューがあります。つまり、キューには各アクティブなクライアントの IP とポート番号があります
ワーカー スレッドはクリティカル セクションにあり、キューからデータをポップし続け、ポップアウトされた各 IP とポート番号にメッセージを送信します。
受信側スレッドは新しい接続を待機するだけで、アクティブなクライアントに加えて新しいクライアントが到着するとすぐに、受信側スレッドはワーカー スレッドがクリティカル セクションを離れて、受信側スレッドがクリティカル セクションに入り、キューに書き込むことができるようにする必要があります。
これはどのように達成できますか?スレッドが EnterCriticalSection を呼び出したときに、他のすべてのスレッドがクリティカル セクションを離れてクリティカル セクションにアクセスできるようにする必要がある方法はありますか (これはある種の優先順位だと思います)。
私のコードでは、ワーカー スレッドは常にクリティカル セクションにあります。受信スレッドがクリティカル セクションに入りたい場合、イベントを設定し、ワーカー スレッドはこのイベントをチェックしてクリティカル セクションを離れます。ワーカー スレッドは、このイベントがリセットされるまで待機し、再びクリティカル セクションのアクセスを取得します。
私のアプローチは正しいですか?これを行うより良い方法はありますか?
DWORD WINAPI workerThreadProcedure(LPVOID param)
{
struct node* sendBuff;
char sendBuffer[600];
while(1)
{
EnterCriticalSection(&cs);
Sleep(500);
if((WaitForSingleObject(data_available_event,0)) == WAIT_OBJECT_0 ) /*check for event*/
{
//Event is Set. Leave critical Section now
LeaveCriticalSection(&cs);
while(WaitForSingleObject(data_available_event,0) == WAIT_OBJECT_0)
{
//Waiting to get REset \r\n");
}
//REset Done
EnterCriticalSection(&cs); //again enter Critical Section.
}
//Going to pop data out
sendBuff = pop();
while(sendBuff != NULL) // while Queue is not empty
{
//sendto() some data on socket
sendBuff = pop();
}
LeaveCriticalSection(&cs);
}
return 0;
}
DWORD WINAPI receiveThreadProcedure(LPVOID param)
{
//recvfrom()
// if received Buffer is from a new Client
SetEvent(data_available_event); /* signal worker thread that data is available and now I want to write to Queue*/
struct node* cur;
char clientPort[12], detail[512], *clientIP = inet_ntoa(clientSocket.sin_addr);
int cliPort = ntohs(clientSocket.sin_port);
itoa(cliPort,clientPort,10);
strcat(clientIP," ");
strcpy(detail,clientIP);
strcat(detail,clientPort);
EnterCriticalSection(&cs);
cur =cread();
cur->data = detail;
cur->n=NULL;
push(cur);
ResetEvent(data_available_event);
LeaveCriticalSection(&cs);
}
編集: 今、このコードを実行すると、新しいクライアントが来たときにスレッドがクリティカルセクションに入るのを受け取り、push()es いくつかのデータを入力してからイベントをリセットした後、ワーカースレッドが再びクリティカルセクションに入りますが、ポップ中に次のエラーが発生します。
Master.exe の 0x01031ba5 で未処理の例外: 0xC0000005: アクセス違反の読み取り場所 0x00000000。