0

我对 Windows (C/C++) 中的 MailSlots 有疑问。

我现在正在尝试制作两个简单的程序,但是最后一步的沟通并不好。

这是我来自 server.cpp 的 int main

    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;
}

似乎服务器正在发送三遍相同的东西。我在调试器中测试了客户端,他做对了,但无法弄清楚为什么服务器会发送三倍相同的东西。

你有什么建议吗 ?

4

2 回答 2

2

邮槽是一种不可靠的传输方式——消息可以随意丢弃。为了确保消息能够通过,发送者使用每个可用的不同协议(将发送者连接到预期的接收者)自动发送一次消息。

您的网络堆栈显然已设置好,因此有三种协议将您的发送方连接到您的接收方。由于它们(可能)通过相对可靠的硬件进行本地通信,没有路由器通过丢弃数据包或类似的方式处理拥塞,因此您可能会获得每个数据包的三个副本。

底线:如果你想使用邮槽,你几乎必须为每个数据包分配一个序列号,这样你就可以跟踪你什么时候已经收到了东西,这样你就可以识别和忽略在接收方重复。

或者,不要使用邮槽。如果(无论出于何种原因)您想要特定于 Windows 的东西,命名管道通常更容易。除非您实际上对代码的可移植性和可互操作性感到困扰,否则套接字可能更简单。

于 2012-10-25T02:36:29.873 回答
0

sizeofstrlen. 调用sizeof(nrr)将始终返回 10。服务器程序将执行 10 个字节的单次写入,即使缓冲区仅包含 2 个有效字节。

替换sizeof1+strlen以解决问题。

例如,在 server.cpp 中如果wrds为 1,nrr则将{ 0x31, 0x00 }在内存中。看似重复的写入实际上是对未初始化内存的单次写入。strlen将为您提供有效字符的计数,终止 null 时为 +1。

首先初始化 nrr 可能是个好主意*nrr = 0。您可以在您认为合适的情况下测试itoa成功if(*nrr)并处理失败。

哦,还有一件事:您正在泄漏手柄。在客户端可能无关紧要,但服务器在每次迭代时都会泄漏一个邮槽的句柄。您应该重用邮槽句柄或在每次迭代时关闭它。

于 2012-10-25T03:24:24.660 回答