Как контролировать время ожидания соединения с Winsock API? - PullRequest
0 голосов
/ 16 октября 2011

Я пишу программу с использованием Winsock API, потому что мой друг хотел, чтобы простая программа проверила и проверила, работает ли сервер Minecraft или нет. Он работает нормально, если он работает, однако, если он не работает, программа зависает до тех пор, пока, я предполагаю, не истечет время ожидания соединения. Другая проблема, если у меня есть что-то вроде этого (псевдокод):

void connectButtonClicked()
{
     setLabel1Text("Connecting");
     attemptConnection();
     setLabel1Text("Done Connecting!");
}

похоже, что пропускает право на попыткуConnection (), полностью игнорируя то, что находится над ним. Я замечаю это, потому что программа зависнет, но она не изменит метку на «Соединение».

Вот мой фактический код подключения:

bool CConnectionManager::ConnectToIp(String^ ipaddr)
{
    if(!m_bValid)
        return false;

    const char* ip = StringToPConstChar(ipaddr);
    m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(isalpha(ip[0]))
    {
        ip = getIPFromAddress(ipaddr);
    }
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr(ip);
    service.sin_port = htons(MINECRAFT_PORT);
    if(m_socket == NULL)
    {
        return false;
    }
    if (connect(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
    {
        closesocket(m_socket);
        return false;
    }
    else
    {
        closesocket(m_socket);
        return true;
    }

    return true;
}

В конструкторе CConnectionManager также есть код для запуска Winsock API и тому подобное.

Итак, как мне избежать этого зависания и разрешить мне обновлять что-то вроде индикатора выполнения во время соединения? Должен ли я сделать соединение в отдельном потоке? Я работал только с потоками в Java, поэтому понятия не имею, как это сделать: /

Также: я использую приложение Windows Form CLR
Я использую Microsoft Visual C ++ 2008 Express Edition

Ответы [ 2 ]

4 голосов
/ 16 октября 2011

Ваш код не пропускает обновление метки.Обновление просто включает в себя выдачу оконных сообщений, которые еще не были обработаны, поэтому вы не видите новый текст перед подключением к сокету.Перед подключением к сокету вам придется накачать очередь сообщений для новых сообщений.

Что касается самого сокета, то, к сожалению, в WinSock API нет времени ожидания подключения.У вас есть два варианта реализации тайм-аута вручную:

1) Предполагая, что вы используете блокирующий сокет (сокеты блокируются по умолчанию), выполните подключение в отдельном рабочем потоке.

2)Если вы не хотите использовать поток, переключите сокет в неблокирующий режим.Подключение сокета всегда завершается немедленно, поэтому ваш основной код не будет заблокирован, и вы получите уведомление позже, если подключение было успешным или нет.Есть несколько способов определить это, в зависимости от того, какой API вы используете - WSAAsyncSelect (), WSAAsyncEvent () или select ().

В любом случае, пока выполняется соединение, запустите таймер на главномнить.Если подключение выполнено успешно, остановите таймер.Если таймер истекает, отсоедините разъем, что приведет к прерыванию соединения с ошибкой.

1 голос
/ 21 октября 2011

Может быть, вы хотите прочитать здесь:

Чтобы гарантировать, что все данные отправляются и принимаются на подключенном сокете до его закрытия, приложение должно использовать shutdown для закрытия соединения перед вызовом closesocket.http://msdn.microsoft.com/en-us/library/ms740481%28v=VS.85%29.aspx

Поскольку вы находитесь в режиме блокировки, некоторые данные все еще могут быть ...

...