2

我有一个非常简单的 Winsock2 TCP 客户端——下面是完整的列表——它只会发送一堆字节。但是,它在网络上运行非常缓慢;数据只是涓涓细流。

这是我尝试并发现的(两台 Windows PC 都在同一个 LAN 上):

  • 从一台机器到另一台机器运行这个应用程序很慢 - 发送 8MB 需要大约 50 秒。
  • 两个不同的服务器——netcat 和一个自定义编写的服务器(就像下面的客户端一样简单)——产生了相同的结果。
  • taskmgr 显示几乎没有使用 CPU 和网络。
  • 在同一台机器上与服务器一起运行这个应用程序很快 - 发送 8MB 需要大约 1-2 秒。
  • 另一个客户端 netcat 工作得很好——发送 20MB 的数据大约需要 7 秒。(我用的是 Cygwin 自带的 nc。)
  • 改变缓冲区大小(1*4096、16*4096 和 128*4096)几乎没有区别。
  • 在不同 LAN 上的 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;
}
4

3 回答 3

2

您可以采取以下措施来获得更好的照片。

  • 您可以检查它在“连接”、“发送”API 调用中花费了多少时间。您可以查看连接呼叫是否有问题。您可以使用分析器来完成,但如果您的应用程序非常慢,您将能够在调试时看到它。
  • 尝试运行 Wireshark(或 Ethereal)来转储您的网络流量,以便您看到 TCP 数据包的传输具有一定的延迟。如果响应很快,那么它只与您的系统有关。如果您发现延迟,那就是路由/网络问题。
  • 您可以运行“路由打印”来检查您的 PC 如何将流量发送到目标计算机 (157.54.144.70)。您将能够查看是否使用了网关并检查不同路由的路由优先级。
  • 尝试发送较小的块。(我的意思是将“bufsz”更改为 1024)。性能和缓冲区大小之间是否存在关联?
  • 检查是否安装了杀毒软件、防火墙应用程序?确保将其关闭。您可以尝试在具有网络支持的安全模式下运行相同的应用程序。
于 2009-10-23T16:13:45.973 回答
1

该应用程序看起来不错,您说它可以在 linux 上正常工作。我不知道这是否会帮助你,但我会比较 - 1)windows的mtu值与linux系统。2) 检查 windows 和 Linux 中的 tcp 接收内存大小。3)检查两个系统的网卡速度是否相同。

于 2009-10-23T04:18:46.207 回答
0

我使用Microsoft 网络监视器 (netmon)和漂亮的TCP Analyzer可视化工具观察数据包,结果发现大量数据包丢失并需要重新传输 - 因此速度很慢,因为重新传输超时 (RTO)。

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

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

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

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

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

我尝试使用第三个盒子作为发件人(与原始发件人相同,一个带有 nForce 芯片组的 Shuttle XPC),这工作顺利 - TCP Analyzer 显示 TCP 会话运行非常流畅。这向我表明问题实际上是由于原始发件箱上的错误 NIC/驱动程序或以太网电缆损坏所致。

于 2009-10-26T22:38:35.360 回答