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

时间:2009-10-23 03:04:46

标签: windows performance networking tcp winsock

我有一个非常简单的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 个答案:

答案 0 :(得分:2)

您可以采取以下措施来获得更好的效果。

  • 您可以查看“连接”,“发送”API调用所花费的时间。您可以看到连接呼叫是否有问题。您可以使用分析器来完成它,但如果您的应用程序非常慢,您将能够在调试时看到它。
  • 尝试运行Wireshark(或Ethereal)来转储网络流量,以便您可以看到TCP数据包是以某种延迟传输的。如果响应速度很快,那么它只与您的系统有关。如果发现延迟,那么就是路由/网络问题。
  • 您可以运行“route print”来检查您的PC如何向目标计算机发送流量(157.54.144.70)。您将能够查看是否使用了网关,并检查不同路由的路由优先级。
  • 尝试发送较小的块。 (我的意思是将“bufsz”改为1024)。性能和缓冲区大小之间是否存在相关性?
  • 检查是否安装了防病毒软件防火墙应用程序?务必将其关闭。您可以尝试在网络支持的安全模式下运行相同的应用程序。

答案 1 :(得分:1)

该应用程序看起来很好,你说它适用于linux。 我不知道这对你有帮助,但我会比较 - 1)使用linux系统的windows的mtu值。 2)检查windows和Linux中的tcp接收mem大小。 3)检查两个系统的网卡速度是否相同。

答案 2 :(得分:0)

我通过使用Microsoft Network Monitor (netmon)使用漂亮的TCP Analyzer可视化工具观察数据包,结果发现大量数据包丢失并需要重新传输 - 因此速度缓慢,因为重新传输超时(RTOS)。

一位同事帮我调试了这个:

  

嗯,从接收器端的这个跟踪来看,它看起来肯定看起来有些数据包没有通过接收器。我还看到这些跟踪中看起来像是一些受损的数据包(比如部分TCP头等)。

     

即使在“好”的跟踪(接收者对netcat客户端的视图)中,我也看到了一些受损的数据包(错误的TCP数据长度等)。但是,错误并不像其他跟踪那样频繁。

     

鉴于这些机器在同一个子网上,没有路由器可能会丢弃数据包。这留下了两个NIC,以太网电缆和以太网交换机。您可以尝试通过在混合中添加第三台机器来隔离坏机器并尝试使用新机器替换先发送器然后替换接收器进行相同的测试。为第三台计算机使用不同的物理端口。如果任何一台原始机器在它和地板插孔之间有一个开关,请尝试从等式中移除该开关。您也可以在原来的两台机器(或直接插入两台机器的不同以太网交换机)之间尝试以太网反向电缆,并查看问题是否仍然存在。

     

由于问题似乎与数据包内容有关,我怀疑问题出在布线上。鉴于发送方有一个NVidia nForce芯片组以太网而接收方有一个Broadcom以太网,我的钱就是发送方的NIC是罪魁祸首。如果它似乎是特定NIC的故障,请尝试关闭NIC的特殊功能,如校验和卸载或大发送卸载。

我尝试使用第三个方框作为发送方(与原始发送方相同,使用带有nForce芯片组的Shuttle XPC),并且运行顺利 - TCP Analyzer显示非常流畅的TCP会话。这告诉我,问题实际上是由于原始发件人盒上的有缺陷的NIC /驱动程序或以太网电缆坏了。