代码之家  ›  专栏  ›  技术社区  ›  xyzzyrz

最小Winsock2应用的性能调试网络吞吐量

  •  2
  • xyzzyrz  · 技术社区  · 15 年前

    我有一个非常简单的winsock2-tcp客户机-下面的完整列表-它只会爆炸一堆字节。然而,它在网络上运行的非常缓慢;数据只是涓涓细流。

    以下是我的尝试和发现(两台Windows PC都在同一局域网上):

    • 从一台机器到另一台机器运行此应用程序很慢-发送8MB需要大约50秒。
    • 两个不同的服务器——netcat和一个定制编写的服务器(与下面的客户机一样简单)——产生了相同的结果。
    • taskmgr显示CPU和网络几乎没有被利用。
    • 使用同一台计算机上的服务器运行此应用程序很快-发送8MB需要大约1-2秒。
    • 另一个客户,netcat,工作得很好——发送20MB数据需要大约7秒。(我使用了Cygwin附带的NC。)
    • 改变缓冲区大小(1*4096、16*4096和128*4096)没有什么区别。
    • 在不同的局域网上的Linux设备上运行几乎相同的代码工作得很好。
    • send 呼叫显示我们大部分时间都在阻塞它。
    • 在服务器端,我们看到一堆<=4K块的接收(不管发送方推送的缓冲区大小如何)。然而,这种情况也发生在其他客户机上,比如全速运行的netcat。

    有什么想法吗?事先谢谢你给我小费。

    #include <winsock2.h>
    #include <iostream>
    
    using namespace std;
    
    enum { bytecount = 8388608 };
    enum { bufsz = 16*4096 };
    
    int main(int argc, TCHAR* argv[])
    {
      WSADATA wsaData;
      WSAStartup(MAKEWORD(2,2), &wsaData);
    
      struct sockaddr_in sa;
      memset(&sa, 0, sizeof sa);
      sa.sin_family = AF_INET;
      sa.sin_port = htons(9898);
      sa.sin_addr.s_addr = inet_addr("157.54.144.70");
      if (sa.sin_addr.s_addr == -1) {
        cerr << "inet_addr: " << WSAGetLastError() << endl;
        return 1;
      }
    
      char *blob = new char[bufsz];
      for (int i = 0; i < bufsz; ++i) blob[i] = (char) i;
    
      SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
      if (s == INVALID_SOCKET) {
        cerr << "socket: " << WSAGetLastError() << endl;
        return 1;
      }
    
      int res = connect(s, reinterpret_cast<sockaddr*>(&sa), sizeof sa);
      if (res != 0) {
        cerr << "connect: " << WSAGetLastError() << endl;
        return 1;
      }
    
      int sent;
      for (int j = 0; j < bytecount; j += sent) {
        sent = send(s, blob, bufsz, 0);
        if (sent < 0) {
          cerr << "send: " << WSAGetLastError() << endl;
          return 1;
        }
      }
    
      closesocket(s);
    
      return 0;
    }
    
    3 回复  |  直到 15 年前
        1
  •  2
  •   alexkr    15 年前

    以下是您可以做的事情,以获得更好的画面。

    • 您可以检查它在“连接”、“发送”API调用中花费了多少时间。您可以查看连接呼叫是否有问题。您可以使用探查器来完成这项工作,但是如果您的应用程序速度非常慢,则可以在调试时看到它。
    • 尝试运行wireshark(或ethereal)来转储您的网络流量,这样您就可以看到TCP数据包是通过某种延迟进行传输的。如果响应速度很快,那么它只与您的系统有关。如果你发现了延迟,那就是路由/网络问题。
    • 您可以运行“route print”来检查您的PC如何将流量发送到目标机器(157.54.144.70)。您将能够看到是否使用了网关,并检查不同路由的路由优先级。
    • 尝试发送较小的块。(我的意思是把“bufsz”改为1024)。性能和缓冲区大小之间是否存在相关性?
    • 检查是否安装了防病毒、防火墙应用程序?一定要把它关掉。您可以尝试在网络支持的安全模式下运行相同的应用程序。
        2
  •  1
  •   Satish    15 年前

    这个应用程序看起来很好,你说它在Linux上工作得很好。 我不知道这是否对你有帮助,但我会比较一下- 1)使用Linux系统的Windows的MTU值。 2)在windows和linux中检查了tcp receive mem的大小。 3)检查两个系统的网卡速度是否相同。

        3
  •  0
  •   xyzzyrz    15 年前

    我看着包裹用 Microsoft Network Monitor (netmon) 和尼斯 TCP Analyzer 可视化工具,结果发现大量的数据包丢失了,需要重新传输,因此速度很慢,因为重新传输超时(RTO)。

    一位同事帮我调试了:

    好吧,从接收端的这个跟踪来看,肯定有一些包没有通过接收端。我还看到了这些跟踪中似乎有一些损坏的数据包(如部分TCP头等)。

    即使在__good_trace(netcat客户机的接收器视图)中,我也会看到一些损坏的数据包(错误的TCP数据长度等)。然而,这些错误并不像在其他跟踪中那样频繁。

    考虑到这些机器在同一个子网中,没有路由器可以用来丢弃数据包。剩下两个网卡、以太网电缆和以太网交换机。您可以尝试通过在混合物中添加第三台机器来隔离坏机器,并尝试使用新机器进行相同的测试,首先更换发送器,然后更换接收器。对第三台机器使用不同的物理端口。如果原来的两台机器中有一台在它和地板千斤顶之间有开关,请尝试从方程式中删除该开关。您还可以尝试在原始两台机器之间使用以太网反向电缆(或直接将两台机器插入的不同以太网交换机),并查看问题是否仍然存在。

    由于问题似乎与数据包内容有关,我怀疑问题出在布线上。考虑到发送方有Nvidia Nforce芯片组以太网,而接收方有Broadcom以太网,我的钱就在发送方的网卡上。如果确实是某个网卡的故障,请尝试关闭该网卡的特殊功能,如校验和卸载或大量发送卸载。

    我尝试使用第三个盒子作为发送器(与原始发送器相同,是一个带有nforce芯片组的Shuttle xpc),这工作得很顺利-TCP分析器显示了非常顺利的TCP会话运行。这表明问题实际上是由于原始发送器盒上的错误NIC/驱动程序,或是以太网电缆损坏造成的。