Winsock connect () постоянно возвращает WSAETIMEDOUT, но PuTTY подключается к тому же порту - PullRequest
4 голосов
/ 28 июля 2010

Вероятно, самая странная ошибка, с которой я когда-либо сталкивался.

Мне нужно подключиться к какому-либо стороннему приложению, работающему под Windows XP Embedded.Сетевое подключение присутствует и работает: я могу подключиться к ожидаемому порту с помощью PuTTY, работающего в Windows XP SP3, и выполнить некоторые операции, подобные 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 и другой с моим приложением, будучи запущенным с того же ПК и подключенным к тому же оборудованию (первые пакеты SYN ниже).

PuTTY:

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, то же сетевое соединение - мое приложение .NET просто подключается к удаленному приложению!Более того, мое оригинальное приложение C прекрасно работает с другого ноутбука под Windows 7 x64.После однодневной заставки у меня есть два ноутбука с Windows XP SP3, с помощью которых мое приложение C не подключается к удаленному клиенту, и один ноутбук с Windows XP SP3 и один Windows 7 x64, где мое приложение C работает без каких-либо проблем.

MyПервым предположением были сетевые драйверы, но приложения PuTTY и .NET просто работают на одном ноутбуке!

Кто-нибудь испытывал нечто подобное и мог бы посоветовать мне?

Спасибо.

Ответы [ 5 ]

1 голос
/ 06 августа 2010

Мне это не подходит:

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

Нет доступа к документации VC, но не должно ли это быть &e->h_addr?

Просто W.A.G. Поскольку IP-блок вашей версии обнуляется, очевидно, что memmove читает из неправильного места и копирует блок неиспользуемой, но обнуленной памяти.

0 голосов
/ 05 августа 2010

Определенно явно укажите IPPROTO_TCP в своем вызове socket, не позволяйте API выбирать за вас. Пока ты не попробовал, не стоит смотреть на что-либо еще.

0 голосов
/ 03 августа 2010

У меня были кое-какие похожие проблемы; вместо WSAETIMEDOUT он возвращал мне WSAEADDRINUSE. setsockopt () решил эту проблему.

Я также предложил бы обновить сокет (..., 0) вызов сокетом (..., IPPROTO_TCP)

0 голосов
/ 04 августа 2010

1-й - Не доверяйте настройкам по умолчанию в API - например, убедитесь, что вы используете протокол TCP в качестве протокола и задаете параметры сокетов, которые вам действительно нужны.Легко запомнить, что вы не статически связываете весь свой код, поэтому вы всегда можете столкнуться с различными версиями и степенями примененных обновлений.Использование всех параметров и значений по умолчанию помогает уменьшить странные и недокументированные побочные эффекты несчетных QFE-ов.

2nd - Похоже, вы строите {x86, x64} Проверьте все возможные различия между сборками x86 и x64.Убедитесь, что вы строите абсолютно чистые обе стороны (то есть явно удаляете все в поле зрения - так называемые смешанные сборки могут всегда происходить при сборке мультиплатформы.

3-й - действительно ли Wireshark замечает трафик из вашего приложения или это простосетевой шум, который он получает? Причина, по которой я спрашиваю, состоит в том, что если нет реального трафика, то это может быть групповая политика и / или брандмауэр - PUTTY, скорее всего, делает явные вызовы API для открытия порта на встроенном брандмауэре.исчерпайте мои идеи на данный момент. О, и у вас есть x64 XP, чтобы попробовать? Просто из любопытства.

0 голосов
/ 28 июля 2010

Поскольку вы подключаетесь к 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
...