Winsock的connect()永久返回WSAETIMEDOUT,但是PuTTY连接在同一个端口上

时间:2010-07-28 00:10:48

标签: debugging sockets tcp winsock

可能是我到目前为止遇到的最奇怪的错误。

我需要连接到在Windows XP Embedded下运行的某些第三方应用程序。网络连接存在且有效:我可以使用在Windows XP SP3上运行的PuTTY连接到预期的端口,并执行一些类似telnet的操作。现在,我的应用程序是一个非常简单的C(VC ++ 2008)程序:

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsaData = { 0 };
    if (SOCKET_ERROR == WSAStartup(MAKEWORD(2, 0), &wsaData))
        return Error("Failed to initialize sockets.");

    SOCKET client = INVALID_SOCKET;

    const char *pserver = "172.22.1.3";

    client = socket(AF_INET, SOCK_STREAM, 0);

    if (INVALID_SOCKET != client)
    {
        sockaddr_in s = { 0 };
        s.sin_family = AF_INET;
        s.sin_port = htons(4799);
        hostent *e = gethostbyname(pserver);
        memmove(&s.sin_addr, e->h_addr, e->h_length);

        std::cout << "Connecting to: " << pserver << std::endl;

        if (SOCKET_ERROR != connect(client, (sockaddr*)&s, sizeof(s)))
        {
            std::cout << "Successfully connected." << std::endl;
        }
        else
            std::cout << "Can't connect: " << WSAGetLastError() << std::endl;
    }

    getchar();

    if (INVALID_SOCKET != client)
        closesocket(client);

    return 0;
}

每次编译和运行此程序时,我都会收到WSAETIMEDOUT错误。困惑的是,我开始深入挖掘并在接收器端生成两个Wireshark转储 - 一个使用PuTTY,另一个使用我的应用程序,从同一台PC运行并连接到相同的设备(下面的第一个SYN数据包)。

腻子:

No.     Time        Source                Destination           Protocol Info
      1 0.000000    172.22.1.61           172.22.1.3            TCP      atc-lm > 4799 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=0 TSV=0 TSER=0

Frame 1 (78 bytes on wire, 78 bytes captured)
Ethernet II, Src: Dell_b8:4a:31 (00:26:b9:b8:4a:31), Dst: EEPD_96:04:48 (00:e0:33:96:04:48)
Internet Protocol, Src: 172.22.1.61 (172.22.1.61), Dst: 172.22.1.3 (172.22.1.3)
Transmission Control Protocol, Src Port: atc-lm (1170), Dst Port: 4799 (4799), Seq: 0, Len: 0

0000  00 e0 33 96 04 48 00 26 b9 b8 4a 31 08 00 45 00   ..3..H.&..J1..E.
0010  00 40 04 a1 40 00 80 06 9b aa ac 16 01 3d ac 16   .@..@........=..
0020  01 03 04 92 12 bf 9a 99 fc ec 00 00 00 00 b0 02   ................
0030  ff ff 2c bd 00 00 02 04 05 b4 01 03 03 00 01 01   ..,.............
0040  08 0a 00 00 00 00 00 00 00 00 01 01 04 02         ..............

我的申请:

No.     Time        Source                Destination           Protocol Info
      1 0.000000    Dell_b8:4a:31         EEPD_96:04:48         FC       [Malformed Packet]

Frame 1 (78 bytes on wire, 78 bytes captured)
Ethernet II, Src: Dell_b8:4a:31 (00:26:b9:b8:4a:31), Dst: EEPD_96:04:48 (00:e0:33:96:04:48)
MDS Header(Unknown(0)/Unknown(0))
[Malformed Packet: FC]

0000  00 e0 33 96 04 48 00 26 b9 b8 4a 31 00 00 00 00   ..3..H.&..J1....
0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0020  00 00 00 00 00 00 00 00 6d 8b 00 00 00 00 b0 02   ........m.......
0030  ff ff 90 73 00 00 02 04 05 b4 01 03 03 00 01 01   ...s............
0040  08 0a 00 00 00 00 00 00 00 00 01 01 04 02         ..............

基本上,整个IP有效负载正在用0x00而不是有效字节擦除。

现在是最奇怪的部分。我为.NET 3.5写了一个类似的程序:

static void Main(string[] args)
{
    var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified);
    socket.Connect("172.22.1.3", 4799);

    Console.WriteLine("Connected");

    Console.ReadLine();
    socket.Disconnect(true);
}

相同的Windows XP SP3 PC,相同的网络连接 - 我的.NET应用程序只是连接到远程应用程序!此外,我的原始C应用程序在Windows 7 x64下从另一台笔记本电脑上运行得很好。经过一天的头带化,我有两台Windows XP SP3笔记本电脑,我的C应用程序无法连接到远程客户端,还有一台Windows XP SP3和一台Windows 7 x64笔记本电脑,我的C应用程序可以毫无问题地工作。

我的第一个猜测是网络驱动程序,但PuTTY和.NET应用程序只能在同一台笔记本电脑上运行!

有没有人经历类似的事情,可以建议我吗?

感谢。

5 个答案:

答案 0 :(得分:1)

这对我来说不合适:

memmove(&s.sin_addr, e->h_addr, e->h_length);
                     ^^^^^^^^^-- here

无法访问VC文档,但不应该是&e->h_addr吗?

只是W.A.G.由于您的版本的IP块已清零,因此有理由认为memmove正在从错误的位置读取并复制一块未使用但未归零的内存。

答案 1 :(得分:0)

由于您要连接到IP地址,请不要使用gethostbyname()(特别是因为您没有检查它是否有错误回复)。改为使用inet_addr():

sockaddr_in s = { 0 }; 
s.sin_family = AF_INET; 
s.sin_port = htons(4799); 
s.sin_addr.s_addr = inet_addr(pserver); // <-- here

答案 2 :(得分:0)

我有一些类似的问题;而不是WSAETIMEDOUT,它回来了我WSAEADDRINUSE。 setsockopt()解决了这个问题。

我还建议你用socket(...,IPPROTO_TCP)更新socket(...,0)调用。

答案 3 :(得分:0)

1st - 不要相信API中的默认值 - 比如确保强制TCP作为协议并且设置实际需要的套接字选项。很容易记住,您并非静态链接所有代码,因此您可以始终面对不同版本和更新程度。强制所有选项和默认值有助于减少不可数量的QFE-s的奇怪和无证副作用。

第二 - 看起来你正在构建{x86,x64}检查x86和x64版本之间的任何可能的差异。确保你建立绝对干净的两面(意味着明确地删除所有东西 - 所谓的混合构建总是在构建多平台时发生。

第3页 - Wireshark是否真的注意到来自您应用的流量,或者只是网络噪音?我问的原因是,如果没有真正的流量,则可以是组策略和/或防火墙 - PUTTY最有可能进行显式API调用以在内置防火墙上打开端口。

这就耗尽了我的想法。哦,你有尝试x64 XP吗?只是出于好奇。

答案 4 :(得分:0)

IPPROTO_TCP电话中明确指定socket,不要让API为您选择。在你尝试之前,不值得查看其他任何内容。