2010-07-28 55 views
4

也许到目前为止,我所遇到的最奇怪的错误上连接。的Winsock的connect()返回永久WSAETIMEDOUT,但腻子同一端口

我需要连接到运行在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 [email protected]@........=.. 
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应用程序无任何问题。

我的第一个猜测是网络驱动程序,但腻子和.NET应用程序只是在同一台笔记本电脑工作!

有没有人有过类似的事情,可以告诉我吗?

谢谢。

回答

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 
+0

不幸的是,没有任何工作。以及getaddrinfo()。 – wasker 2010-07-28 02:01:49

+0

转换虚线四边形是gethostbyname()的已知和支持的功能。当你知道你有一个虚线的四元组时,调用inet_addr()会更有效率。 – 2010-07-28 13:45:24

+0

我的意图是移除对memmove()的调用,以防使用错误的指针或字节长度来破坏内存。 – 2010-07-28 19:03:04

0

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

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

0

月1日 - 不要相信违约的API - 就像确保您强制TCP的协议,你设置你的实际需要套接字选项。很容易记住,您不是静态链接所有代码,因此您始终可以应用不同的版本和更新程度。强制所有选项和默认值有助于减少不可数的QFE-s的奇怪和无证的副作用。

2日 - 看起来你正在构建{86,64}检查您的x86和x64之间建立任何可能的diff。确保你建立完全干净的双方(意味着明确删除所有内容 - 所谓的混合构建总是可以在构建多平台时发生。

3日 - 是否Wireshark的通知实际上流量从应用还是只是它得到一个网络的噪音?我想问的原因是,如果没有真正的流量则是可以在组策略和/或防火墙 - 腻子最有可能使明确的API调用来打开一个端口上内置的防火墙。

,在这一点耗尽了我的想法。哦,你有64位XP试试吗?只是出于好奇。

0

绝对明确地在你的电话socket指定IPPROTO_TCP,不要让API供您选择。直到你尝试过,不值得去看别的东西。

1

这看起来不正确的对我说:

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

不必进入VC文档,但它不应该是&e->h_addr

只是W.A.G.由于你的版本的IP块已经被清零,所以理由是memmove正在从错误的地方读取数据,并复制一块未使用但是已被清零的内存。

+0

也不应该是memcpy,而不是memmove – grieve 2010-08-18 20:35:58