TCP 连接超时问题~
前几天发了一个帖子, 今天发现问题依旧没解决
TCP如果连接不上 将会一直阻塞在那 将近20秒的时间,让人难以忍受。
所以下面我写了下面的代码, 希望只要等待5秒就返回,可是失败了~~~ 求指点;主线程一定要阻塞着的,连接上以后才能有其他操作;
*.cpp:
BOOL CSelectModelDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE);// 设置大图标
SetIcon(m_hIcon, FALSE);// 设置小图标
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 2);
if(::WSAStartup(sockVersion, &wsaData) != 0)
{
MessageBox(_T("初始化套接字库失败,将退出程序"));
return FALSE;
}
m_st = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_clientst == NULL )
{
MessageBox(_T("建立套接字失败"));
return FALSE;
}
sockaddr_in psaddr;
psaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
psaddr.sin_family = AF_INET;
psaddr.sin_port = htons(5555);
if(SOCKET_ERROR == ::bind(m_st,(sockaddr*)&psaddr,sizeof(psaddr)))
{
MessageBox(_T("绑定套接字失败"));
return FALSE;
}
if(SOCKET_ERROR == listen(m_st, 5))
{
MessageBox(_T("监听失败"));
return FALSE;
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CSelectModelDlg::OnBnClickedButton1()
{
m_clientst = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
CreateThread(NULL,0,ConnectProc,(LPVOID)m_clientst,0,NULL);
sockaddr_in psaddr;
psaddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.133");
psaddr.sin_family = AF_INET;
psaddr.sin_port = htons(5555);
if(SOCKET_ERROR == connect(m_clientst,(sockaddr *)&psaddr,sizeof(psaddr)))
{
AfxMessageBox("连接出错");
}
}
DWORD WINAPI CSelectModelDlg::ConnectProc(LPVOID lpParam)
{
SOCKET m_clientt = (SOCKET)lpParam;
struct timeval timeout;
fd_set fs;
FD_ZERO(&fs);
FD_SET(m_clientt,&fs);
timeout.tv_sec= 5;
timeout.tv_usec= 0;
select(0,&fs,&fs,0,&timeout);
return 0;
}
*.h
public:
SOCKET m_st;
SOCKET m_clientst;
static DWORD WINAPI ConnectProc(LPVOID lpParam);
[最优解释]
int iMode = 1; //0:阻塞
ioctlsocket(socketc,FIONBIO, (u_long FAR*) &iMode);//非阻塞设置
[其他解释]
首先,主线程一定要阻塞着的,这种需求很费解
按照LZ的做法,开子线程是多余的,直接将select放主线程就搞定
[其他解释]
这个超时时间没法设置,是它内部有个算法。
但是你可以把socket设置成异步的,然后用select控制超时
------其他解决方案--------------------
[quote=
这样吗?[/quote]
ioctlsocket设置套接字为非阻塞模式
然后调用select
判断返回值是否为连接超时。
[其他解释]
你申请个线程,把主线程sleep 5秒了,看子线程是否有链接上。没连接上就返回。一般情况连接或者监听都要开线程的
[其他解释]