如何使用Winsock API控制连接超时? [英] How to control the connect timeout with the Winsock API?

查看:111
本文介绍了如何使用Winsock API控制连接超时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Winsock API编写程序,因为一个朋友想要一个简单的程序来检查并查看 Minecraft 服务器是否正在运行。如果正在运行,它可以正常运行,但是,如果未运行,则程序将冻结直到我认为连接超时为止。另一个问题是,如果我有这样的东西(伪代码):

I'm writing a program using the Winsock API because a friend wanted a simple program to check and see if a Minecraft server was running or not. It works fine if it is running, however if it is not running, the program freezes until, I'm assuming, the connection times out. Another issue is, if I have something like this (pseudo-code):

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

它似乎跳过了对tryConnection()的访问,而完全忽略了上面的内容。我注意到这是因为该程序将冻结,但是它不会将标签更改为正在连接。

it seems to skip right to attemptConnection(), completely ignoring whats above it. I notice this because the program will freeze, but it wont change the label to "Connecting".

这是我的实际连接代码:

Here is my actual connection code:

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等的代码。

There is also code in the CConnectionManager's contructor to start up Winsock API and such.

那么,如何避免这种冻结,并允许我在连接期间更新进度条之类的内容?我是否必须在单独的线程中进行连接?我只使用过Java中的线程,所以不知道该怎么做:/

So, how do I avoid this freeze, and allow me to update something like a progress bar during connection? Do I have to make the connection in a separate thread? I have only worked with threads in Java, so I have no idea how to do that :/

另外:我正在使用CLR Windows窗体应用程序

我正在使用Microsoft Visual C ++ 2008 Express Edition

Also: I am using a CLR Windows Form Application
I am using Microsoft Visual C++ 2008 Express Edition

推荐答案

您的代码不会跳过标签更新。该更新仅涉及发出尚未处理的窗口消息,这就是为什么在连接套接字之前看不到新文本出现的原因。连接套接字之前,您必须为新消息泵送消息队列。

Your code does not skip the label update. The update simply involves issuing window messages that have not been processed yet, that is why you do not see the new text appear before connecting the socket. You will have to pump the message queue for new messages before connecting the socket.

关于套接字本身,不幸的是WinSock API中没有连接超时。您有两种选择来实现手动超时:

As for the socket itself, there is no connect timeout in the WinSock API, unfortunately. You have two choices to implement a manual timeout:

1)假设您正在使用阻塞套接字(默认情况下套接字处于阻塞状态),请在单独的工作线程中执行连接

1) Assuming you are using a blocking socket (sockets are blocking by default), perform the connect in a separate worker thread.

2)如果您不想使用线程,则将套接字切换为非阻塞模式。连接套接字总是会立即退出,因此您的主代码不会被阻止,然后您会在以后收到连接成功的通知。有几种方法可以检测到这种情况,具体取决于您使用的是WSAAsyncSelect(),WSAAsyncEvent()还是select()。

2) If you don't want to use a thread then switch the socket to non-blocking mode. Connecting the socket will always exit immediately, so your main code will not be blocked, then you will receive a notification later on if the connection was successful or not. There are several ways to detect that, depending on which API you use - WSAAsyncSelect(), WSAAsyncEvent(), or select().

无论哪种方式,连接都是在进行中,请在主线程中运行一个计时器。如果连接成功,请停止计时器。如果计时器过去了,请断开套接字的连接,这将导致连接异常中止。

Either way, while the connect is in progress, run a timer in your main thread. If the connect succeeds, stop the timer. If the timer elapses, disconnect the socket, which will cause the connect to abort with an error.

这篇关于如何使用Winsock API控制连接超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆