我编写了一个小型 C/C++ Windows Mobile 6.5 客户端应用程序,它连接到服务器并向该服务器发送一些数据。服务器位于我的内部无线网络中,外部无法访问。
我的奇怪行为:
即使我的移动设备上未启动 Wi-Fi,客户端应用程序中的 connect() 也会返回成功(!= SOCKET_ERROR),但情况并非如此,因为服务器只能在无线网络中访问.
如果我的移动设备上未启动 Wi-Fi,如果 connect() 和 send() 之间存在 Sleep (1000),则 send() 会失败并显示 WSAECONNRESET,但如果没有 Sleep()在 connect() 和 send() 之间,send() 成功! (只有在执行 read() 时,我才最终得到 WSAECONNRESET 错误)。
非常可怕的是,在实际上无法到达服务器的情况下,我仍然可以成功连接()和发送()
根据要求,这里是示例代码:
#include <windows.h>
#include <Winsock2.h>
#include "dbgview.h"
# define FxMemZero(buf,len) RtlZeroMemory ((VOID*)(buf),(SIZE_T)(len))
# define FxMemCopy(dst,src,len) RtlCopyMemory ((VOID*)(dst),(CONST VOID*)(src),(SIZE_T)(len))
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
SOCKET proxy_connection;
WSADATA wsadata;
if( 0 != WSAStartup (MAKEWORD(1, 1), &wsadata))
return -1;
proxy_connection = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if(proxy_connection == INVALID_SOCKET) {
// error creating the socket
DbgViewTraceError((L"main", L"error creating socket."));
return -1;
}
// try to connect
UINT proxy_ip_ = 0x00000000;
CHAR* proxy_0_ = "192.168.1.105";
UINT proxy_port = 3100;
// get the proxy ip
{
struct hostent *he_;
if((he_ = gethostbyname(proxy_0_)) == NULL) {
DbgViewTraceWarning((L"main", L"error %d resolving hostname %hs", WSAGetLastError(), proxy_0_));
return -1;
}
FxMemCopy((PBYTE)&proxy_ip_, (PBYTE)he_->h_addr, he_->h_length);
}
// prepare the connection data
sockaddr_in saddr_;
FxMemZero(&saddr_,sizeof(sockaddr_in));
saddr_.sin_family = AF_INET;
saddr_.sin_addr.S_un.S_addr = proxy_ip_;// address
saddr_.sin_port = htons((USHORT)proxy_port);
// do the conection
if(SOCKET_ERROR == connect(proxy_connection, (SOCKADDR*) &saddr_, sizeof(saddr_))) {
// error connecting to the proxy
DbgViewTraceWarning(( L"main", L"error %d connecting to %hs:%d", WSAGetLastError(), proxy_0_, proxy_port));
closesocket(proxy_connection);
proxy_connection = INVALID_SOCKET;
return -1;
}
DbgViewTraceInfo(( L"main", L"SUCCESS. connected to %hs:%d.", proxy_0_, proxy_port));
CHAR* buffer_ = "Momo";
UINT count_ = strlen(buffer_);
DWORD total_ = 0;
DWORD sent_ = 0;
while(total_ < count_) {
// ISSUE: IF the WIFI is not started on the mobile, the connect returns success AND the send() returns success, even though with putty
// on the mobile, a telnet on 192.168.1.105:3100 will fail with: "Network error: Connection reset by peer"
// IF I add a long-enough Sleep() between the connect() and the send(), the send() will fail with: WSAECONNRESET
//Sleep(5000);
if(SOCKET_ERROR == (sent_ = send(proxy_connection, (const char*)buffer_ + total_, count_ - total_, 0))) {
// error sending data to the socket
DbgViewTraceError((L"main", L"error %d sending data to proxy", WSAGetLastError()));
return -1;
}
total_ += sent_;
}
DbgViewTraceInfo((L"main", L"send() SUCCESS"));
return 0;
}
结果是:
main [INFO ] SUCCESS. connected to 192.168.1.105:3100.
main [INFO ] send() SUCCESS
main [INFO ] SUCCESS. connected to 192.168.1.105:3100.
main [ERROR ] error 10054 sending data to proxy
所以问题是:
为什么connect()会成功?我如何确定确实存在真正的联系?
为什么send()会成功?
为什么在 connect() 和 send() 之间使用 Sleep() 时行为会有所不同?
问题似乎出在 ActiveSync 上。如果 ActiveSync 正在运行,我会得到上述行为(connect() 和 send() 报告成功,即使它们没有成功)。如果 ActiveSync 未运行,gethostbyname() 会失败并显示:
WSAENETDOWN -> 如果 Wi-Fi 被禁用
WSAHOST_NOT_FOUND -> 如果 Wi-Fi 已启用
哪个是正确的!
怎么会这样呢? ActiveSync 正在做什么,会毁掉一切?我怎样才能避免这个问题?我的意思是,当没有运行 ActiveSync 时,我无法确定用户是否正在运行我的应用程序,那么当 ActiveSync 运行时我可以做什么来避免这种行为?