我写了一个升级程序,服务器端采用多线程和重叠I/O模型,客户端采用重叠I/O模型。程序在局域网内没问题,在外网客户端安装时如果客户是通过ADSL拨号方式连接的可以正常升级,如果客户是通过直连的方式连接(中国移动的网络)则会出现不能升级的情况。前两天我去现场看了下,感觉域名是可以解析的(我通过域名连接服务器),而且客户端直接ping服务器也是ping的通的。我的升级客户端程序应该是在connect的时候连接不上。由于客户需要日常经营,我也不方便在那调试,根据我的判断应该就是connect了。我不太清楚这两种连接方式有什么区别,而且客户端明明是可以解析服务器端的,为什么连接不上呢?希望有相关经验的高手指点!!
// 读取服务器备用域名
if( GetPrivateProfileString("UPDATE_SERVER", "NAME", "", szServerName, sizeof(szServerName), filePath) == 0 )
{
MessageBox( SETERRORINFO("GetPrivateProfileString", "读取配置文件NAME字段失败."), m_MessageBoxTitle, MB_OK | MB_ICONSTOP );
return false;
}
if( (pHostent = gethostbyname( szServerName )) == NULL )
{
MessageBox( GETERRORINFO("gethostbyname"), m_MessageBoxTitle, MB_OK | MB_ICONSTOP );
return false;
}
m_addr.sin_addr = *(struct in_addr *)pHostent->h_addr;
hostent->h_addr_list[0][1]=xxx
hostent->h_addr_list[0][2]=xxx
hostent->h_addr_list[0][3]=xxx我是直接取的h_addr_list[0][0],不知它会不会不在[0][0]的位置,而在1、2、3等位置?如果那样的话,我的程序也试解析不了的。
BOOL CClientDlg::InitSocket()
{
// 声明变量
int nReturn = 0;
int nErrorCode = 0;
int nRecvBuffLen = MAX_RECV_BUFFER;
u_long arg = 1;
char szHostName[MAX_HOST_NAME_LEN] = "";
LPHOSTENT pHostent = NULL; // 创建socket对象
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
if( m_socket == INVALID_SOCKET )
{
::PostMessage( m_hWnd, WM_MESSAGE_BOX, (WPARAM)GETERRORINFO("socket"), (LPARAM)m_MessageBoxTitle );
return false;
} // 设置套接字非阻塞模式
nReturn = ioctlsocket( m_socket, FIONBIO, &arg );
if( nReturn == SOCKET_ERROR )
{
::PostMessage( m_hWnd, WM_MESSAGE_BOX, (WPARAM)GETERRORINFO("ioctlsocket"), (LPARAM)m_MessageBoxTitle );
return false;
} // 设置发送缓冲区长度
setsockopt( m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&nRecvBuffLen, sizeof(nRecvBuffLen) ); // socket连接
while( m_bRunning )
{
nReturn = connect( m_socket, (struct sockaddr*)&m_addr, sizeof(struct sockaddr) );
if ( nReturn == SOCKET_ERROR )
{
nErrorCode = WSAGetLastError();
// 链接未能立即完成或处于监听状态
if( WSAEWOULDBLOCK == nErrorCode || WSAEINVAL == nErrorCode )
{
Sleep( 100 );
continue;
} // 链接已经建立
else if( WSAEISCONN == nErrorCode )
{
return true;
}
else if( WSAEALREADY == nErrorCode )
{
::PostMessage( m_hWnd, WM_MESSAGE_BOX, (WPARAM)SETERRORINFO("connect", "连接服务器失败, 请检查IP地址和端口配置."), (LPARAM)m_MessageBoxTitle );
return false;
}
else
{
::PostMessage( m_hWnd, WM_MESSAGE_BOX, (WPARAM)GETERRORINFO("connect"), (LPARAM)m_MessageBoxTitle );
return false;
}
} // 链接成功建立
if( 0 == nReturn )
{
return true;
}
} return true;
}
连接时弹出“连接服务器失败, 请检查IP地址和端口配置.",也就是说产生的错误是:WSAEALREADY。但不可能是我前面已经打开了,因为我是第一次调用,而且机器重启调用依然这样。