【问题标题】:C++ TCP Winsock Server receiving the same packet many timesC++ TCP Winsock Server多次接收同一个数据包
【发布时间】:2012-09-08 16:58:23
【问题描述】:

我编写了一个非常简单的 C++ 服务器,我从 Java 应用程序连接到它。 C++ 服务器使用winsock2。我正在从我的客户端向服务器发送 UTF8 编码的数字,并且在收到这些数字后,我希望服务器执行一个操作。但是,我的服务器似乎正在接收一系列数字。目前,我让服务器每 1 毫秒侦听一次新消息。

这是我接收消息的 C++ 服务器代码:

  bool receive()
     {
          char buffer[1024];
          int inDataLength=recv(Socket,buffer,sizeof(buffer),0);
          if(buffer[0] != '\0')
          {
                     std::cout<<"Client: ";
                     std::cout << buffer;
                     sendKey(string(buffer));  
          }
          else if (inDataLength == 0) //Properly closed connection
          {
             std::cout<<"Connection lost..\r\n";
             return false;
          }    
          return true;
     }

这是在这样的循环中调用的:

 while ( receive() )
{
      Sleep(1);
}

这是我的 java 客户端代码,用于发送消息,其中输出为 OutputStream = socket.getOutputStream():

public void send(String msg)
{
        try {
            out.write( msg.getBytes("UTF8") );
            out.flush();
            Thread.sleep(100);
        } catch (SocketException e) {
            Global.error("Connection error..");
            //e.printStackTrace();
        } catch (UnsupportedEncodingException e) {

        } catch (IOException e) {
            Global.error("Never connected..\r\n");
        } catch (Exception e)
        { Global.error("Sending failed..\r\n"); }
    }

我得到的是服务器接收例如数字 1,然后是 2,然后是 12,然后是 121 等。没有特定的模式,除非服务器一次接收 2 个数字,它永远不会再开始只接收一个.这是我的 java 代码中唯一将任何内容发送到服务器的地方,并且我在每条消息之后刷新缓冲区,所以我认为问题出在我的服务器上,但我对问题一无所知。

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 记录要发送的调用。生成字符串会不会有问题?睡觉的原因是什么?
  • 感谢您的回复,我已经在我的应用程序中记录了要发送的调用(在示例中删除了它们),它们仅在预期时调用而不重复。此外,服务器上的睡眠是因为循环使 cpu 最大化,并且 java 应用程序上的睡眠与服务器读取相同(或在这种情况下更慢)。
  • 我应该承认 winsock 对我来说是很久以前的事了,但是 recv 应该是阻塞的。如果您只从客户端发送一条消息会发生什么?

标签: java c++ sockets tcp winsock


【解决方案1】:

您忘记了最重要的检查:

int inDataLength=recv(Socket,buffer,sizeof(buffer),0);
if (inDataLength == -1 ) {
    std::cerr << "receive error: " << GetLastError() << std::endl;
    return false;
}
...

这实际上可能是您的循环占用如此多 CPU 时间的原因。

【讨论】:

  • 他还应该检查 EOS,这更可能是导致无限循环的原因。
  • 我认为他有:else if (inDataLength == 0) //Properly closed connection
  • 同意。但是他应该在检查缓冲区内容之前检查它,而不是之后,当他看到它时他应该关闭套接字。
【解决方案2】:

考虑到睡眠,recv 似乎没有阻塞。看看Winsock recv() does not block。您需要检查返回值中的错误。

【讨论】:

  • 我要补充一点,您需要在检查缓冲区之前检查返回值。鉴于您的缓冲区不是堆栈并且您没有设置/清除它(使用类似 memset 的东西),缓冲区中的任何值(这是堆栈上的值)都可能导致您的第一个 if 执行,即使您这样做了收不到任何数据。在检查缓冲区之前首先检查 inDataLength 值(包括错误条件)。
  • 睡眠更可能只是在浪费时间。新手倾向于在网络代码中乱扔垃圾,徒劳地试图让它们更好地工作。
猜你喜欢
  • 1970-01-01
  • 2020-12-11
  • 1970-01-01
  • 2013-06-20
  • 2011-04-25
  • 2015-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多