0

Windows(C / C ++)のMailSlotsに問題があります。

今、2つの簡単なプログラムを作ろうとしていますが、最後のステップでコミュニケーションが良くありません。

これはserver.cppからの私のintメインです

    int main()
{
HANDLE      ss, sc, sc2r;
   LPCTSTR     errMsg;

   ss = CreateMailslot("\\\\.\\mailslot\\ss", 0, MAILSLOT_WAIT_FOREVER, NULL);
   if (ss == INVALID_HANDLE_VALUE) 
   {
       printf("Invalid ss value");
       return -1;
   }

   for (;;)
   {
       DWORD   msgSize;
       DWORD nr;
       BOOL    err;

       /* Get the size of the next record */
       err = GetMailslotInfo(ss, 0, &msgSize, 0, 0);
           char x[100];
           char nrr[10];

       if (msgSize != (DWORD)MAILSLOT_NO_MESSAGE)
       {
               DWORD   numRead;
               /* Read the record */
               err = ReadFile(ss, x, msgSize, &numRead, 0);
               int wrds=count(x)+1;
               sc = CreateFile("\\\\*\\mailslot\\sc", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
               itoa(wrds,nrr,10);

               err = WriteFile(sc, nrr, sizeof(nrr), &nr, 0);
               //cout<<err<<endl;

               //cout<<x;

               //cout<<err;
               strrev(x);
               err=WriteFile(sc, x, sizeof(x), &nr, 0);
           }   
       }
  return(0);
}

クライアントソースは次のとおりです。

int main()
{
   HANDLE      ss, sc, sc2;
   LPCTSTR     errMsg;
   BOOL        err;
   DWORD       numWritten;

   sc = CreateMailslot("\\\\.\\mailslot\\sc", 0, MAILSLOT_WAIT_FOREVER, NULL);
   ss = CreateFile("\\\\*\\mailslot\\ss", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

   if (ss == INVALID_HANDLE_VALUE) 
   {
       printf("CreateFile failed. ");  
       // Close any mailslot we opened
       if (ss != INVALID_HANDLE_VALUE) CloseHandle(ss);
       return -1;
   }

   char x[100];
   char z[100];

   printf("Write the damn sentence:");
   cin.getline(x,100);
   err = WriteFile(ss, x, sizeof(x), &numWritten, 0);
   if (!err) printf("WriteFile failed. ");
   DWORD rd;

   ReadFile(sc,x,sizeof(x),&rd,NULL);
   cout<<x<<endl;
   ReadFile(sc,z,sizeof(z),&rd,NULL);
   cout<<z;

   return 0;
}

サーバーが同じものを3回送信しているようです。私はデバッガーでクライアントをテストし、彼はそれを正しく理解しましたが、サーバーが同じものを3回送信している理由を理解できません。

何か提案はありますか ?

4

2 に答える 2

2

メールスロットは信頼できないトランスポートです。メッセージは自由にドロップできます。メッセージが確実に通過するようにするために、送信者は、使用可能な各個別のプロトコル(その送信者を目的の受信者に接続する)を使用して、メッセージを1回自動的に送信します。

ネットワークスタックは明らかに設定されているため、送信者を受信者に接続するプロトコルは3つあります。それらは(おそらく)ローカルで通信しているため、パケットをドロップするなどして輻輳を処理するルーターのない比較的信頼性の高いハードウェアを介して、すべてのパケットの3つのコピーを取得する可能性があります。

結論:メールスロットを使用する場合は、ほとんどの場合、各パケットにシリアル番号を割り当てる必要があります。これにより、すでに何かを受信したことを追跡できるため、認識して無視することができます。受信側で重複します。

または、メールスロットを使用しないでください。(何らかの理由で)Windowsに固有の何かが必要な場合は、名前付きパイプの方が一般的に簡単です。コードが移植可能で相互運用可能であることに実際に悩まされていない限り、ソケットはおそらくさらに単純です。

于 2012-10-25T02:36:29.873 に答える
0

あなたはと混同sizeofしていstrlenます。呼び出しsizeof(nrr)は常に10を返します。バッファに有効なバイトが2つしかない場合でも、サーバープログラムは10バイトの単一書き込みを実行します。

問題を解決するには、に置き換えsizeofてください。1+strlen

たとえば、server.cppでwrdsが1の場合、nrr{ 0x31, 0x00 }メモリ内にあります。繰り返し書き込みのように見えるのは、実際には初期化されていないメモリの1回の書き込みです。strlen有効な文字数が表示され、終了ヌルの場合は+1になります。

最初にnrrを初期化することをお勧めします*nrr = 0。成功したことをテストし、itoa適切と思わif(*nrr)れる障害を処理できます。

ああ、そしてもう1つ:あなたはハンドルを漏らしています。クライアントではそれほど重要ではないかもしれませんが、サーバーは反復ごとにメールスロットへのハンドルをリークします。メールスロットハンドルを再利用するか、反復ごとに閉じる必要があります。

于 2012-10-25T03:24:24.660 に答える