通过USB蓝牙适配器连接server端程序失败!?
时间:10-02
整理:3721RD
点击:
大家好,我现在在开发一个Windows应用程序通过蓝牙连接移动设备上的一个程序,但是基于蓝牙的socket连接总是失败!
为了简化问题,我用另一个windows应用程序加另一个蓝牙适配器来代替移动设备上的程序及蓝牙模块,来验证我的客户端程序!
我的客户端程序和模拟的服务端程序都是运行在XP SP3上,各有一个USB bluetooth dongle, 服务端和客户端程序如下,服务端能给成功listen, 并阻塞在accept上,客户端程序却一连接就失败!
我又试着在服务端和客户端把BT_PORT_ANY作port的值, 可是还是连不上!
// RunServerMode runs the application in server mode. It opens a socket, connects it to a
// remote socket, transfer some data over the connection and closes the connection.
ULONG RunServerMode(int iMaxCxnCycles)
{
ULONG ulRetCode = 0;
int iAddrLen = sizeof(SOCKADDR_BTH), iCxnCount = 0, iLengthReceived = 0, iTotalLengthReceived = 0;
char szDataBuffer[CXN_TRANSFER_DATA_LENGTH] = {0};
char * pszDataBufferIndex = NULL;
LPTSTR lptstrThisComputerName = NULL;
DWORD dwLenComputerName = MAX_COMPUTERNAME_LENGTH + 1;
SOCKET LocalSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET;
WSAVERSION wsaVersion = {0};
WSAQUERYSET wsaQuerySet = {0};
SOCKADDR_BTH SockAddrBthLocal = {0};
LPCSADDR_INFO lpCSAddrInfo = NULL;
BOOL bContinue;
// Both of these fixed-size allocations can be on the stack
if ( ( lpCSAddrInfo = (LPCSADDR_INFO) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSADDR_INFO) ) ) == NULL)
{
printf("!ERROR! | Unable to allocate memory for CSADDR_INFO\n");
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("HeapAlloc() for CSADDR_INFO (address) is OK!\n");
if ( ( lptstrThisComputerName = (LPTSTR) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwLenComputerName ) ) == NULL)
{
printf("!ERROR! | Unable to allocate memory for CSADDR_INFO\n");
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("HeapAlloc() for CSADDR_INFO (local computer name) is OK!\n");
if ( !GetComputerName(lptstrThisComputerName, &dwLenComputerName) )
{
printf("=CRITICAL= | GetComputerName() call failed. WSAGetLastError=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
{
printf("GetComputerName() is pretty fine!\n");
printf("Local computer name: %S\n", lptstrThisComputerName);
}
// Open a bluetooth socket using RFCOMM protocol
printf("Opening local socket using socket()...\n");
if ( ( LocalSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | socket() call failed. WSAGetLastError = [%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (LocalSocket != INVALID_SOCKET))
{
printf("*INFO* | socket() call succeeded! Socket = [0x%X]\n", LocalSocket);
}
// Setting address family to AF_BTH indicates winsock2 to use Bluetooth port
SockAddrBthLocal.addressFamily = AF_BTH;
// Valid ports are 1 - 31
//SockAddrBthLocal.port = BT_PORT_ANY;
SockAddrBthLocal.port = 5;
// bind() associates a local address and port combination
// with the socket just created. This is most useful when
// the application is a server that has a well-known port
// that clients know about in advance.
if ( bind(LocalSocket, (struct sockaddr *) &SockAddrBthLocal, sizeof(SOCKADDR_BTH) ) == SOCKET_ERROR)
{
printf("=CRITICAL= | bind() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (bind(LocalSocket, (struct sockaddr *) &SockAddrBthLocal, sizeof(SOCKADDR_BTH) ) != SOCKET_ERROR))
{
printf("*INFO* | bind() call succeeded!\n");
}
if ( ( ulRetCode = getsockname(LocalSocket, (struct sockaddr *)&SockAddrBthLocal, &iAddrLen) ) == SOCKET_ERROR)
{
printf("=CRITICAL= | getsockname() call failed w/socket = [0x%X]. WSAGetLastError=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
{
printf("getsockname() is pretty fine!\n");
printf("Local address: 0x%x\n", SockAddrBthLocal.btAddr);
}
// CSADDR_INFO
lpCSAddrInfo[0].LocalAddr.iSockaddrLength = sizeof( SOCKADDR_BTH );
lpCSAddrInfo[0].LocalAddr.lpSockaddr = (LPSOCKADDR)&SockAddrBthLocal;
lpCSAddrInfo[0].RemoteAddr.iSockaddrLength = sizeof( SOCKADDR_BTH );
lpCSAddrInfo[0].RemoteAddr.lpSockaddr = (LPSOCKADDR)&SockAddrBthLocal;
lpCSAddrInfo[0].iSocketType = SOCK_STREAM;
lpCSAddrInfo[0].iProtocol = BTHPROTO_RFCOMM;
// If we got an address, go ahead and advertise it.
ZeroMemory(&wsaQuerySet, sizeof(WSAQUERYSET));
wsaQuerySet.dwSize = sizeof(WSAQUERYSET);
wsaQuerySet.lpServiceClassId = (LPGUID) &g_guidServiceClass;
// should be something like "Sample Bluetooth Server"
wsaQuerySet.lpszServiceInstanceName = lptstrThisComputerName;
wsaQuerySet.lpszComment = L"Example Service instance registered in the directory service through RnR";
wsaQuerySet.dwNameSpace = NS_BTH;
wsaQuerySet.dwNumberOfCsAddrs = 1; // Must be 1.
wsaQuerySet.lpcsaBuffer = lpCSAddrInfo; // Required.
// As long as we use a blocking accept(), we will have a race
// between advertising the service and actually being ready to
// accept connections. If we use non-blocking accept, advertise
// the service after accept has been called.
if ( WSASetService(&wsaQuerySet, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR)
{
printf("=CRITICAL= | WSASetService() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("WSASetService() looks fine!\n");
// listen() call indicates winsock2 to listen on a given socket for any incoming connection.
if ( listen(LocalSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("=CRITICAL= | listen() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (listen(LocalSocket, SOMAXCONN) != SOCKET_ERROR))
{
printf("*INFO* | listen() call succeeded!\n");
}
for ( iCxnCount = 0; (0 == ulRetCode) && ( (iCxnCount < iMaxCxnCycles) || (iMaxCxnCycles == 0) ); iCxnCount++ )
{
printf("\n");
// accept() call indicates winsock2 to wait for any
// incoming connection request from a remote socket.
// If there are already some connection requests on the queue,
// then accept() extracts the first request and creates a new socket and
// returns the handle to this newly created socket. This newly created
// socket represents the actual connection that connects the two sockets.
if ( ( ClientSocket = accept(LocalSocket, NULL, NULL) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | accept() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
break; // Break out of the for loop
}
if ( (2 <= g_iOutputLevel) | (ClientSocket != INVALID_SOCKET))
{
printf("*INFO* | accept() call succeeded. CientSocket = [0x%X]\n", ClientSocket);
}
// Read data from the incoming stream
bContinue = TRUE;
pszDataBufferIndex = &szDataBuffer[0];
while ( bContinue && (iTotalLengthReceived < CXN_TRANSFER_DATA_LENGTH) )
{
// recv() call indicates winsock2 to receive data
// of an expected length over a given connection.
// recv() may not be able to get the entire length
// of data at once. In such case the return value,
// which specifies the number of bytes received,
// can be used to calculate how much more data is
// pending and accordingly recv() can be called again.
iLengthReceived = recv(ClientSocket, pszDataBufferIndex, (CXN_TRANSFER_DATA_LENGTH - iTotalLengthReceived), 0);
switch ( iLengthReceived )
{
case 0: // socket connection has been closed gracefully
printf("Socket connection has been closed gracefully!\n");
bContinue = FALSE;
break;
case SOCKET_ERROR:
printf("=CRITICAL= | recv() call failed. Error=[%d]\n", WSAGetLastError());
bContinue = FALSE;
ulRetCode = 1;
break;
default: // most cases when data is being read
pszDataBufferIndex += iLengthReceived;
iTotalLengthReceived += iLengthReceived;
if ( (2 <= g_iOutputLevel) | (iLengthReceived != SOCKET_ERROR))
{
printf("*INFO* | Receiving data of length = [%d]. Current Total = [%d]\n", iLengthReceived, iTotalLengthReceived);
}
break;
}
}
if (ulRetCode == 0)
{
if ( CXN_TRANSFER_DATA_LENGTH != iTotalLengthReceived )
{
printf("+WARNING+ | Data transfer aborted mid-stream. Expected Length = [%d], Actual Length = [%d]\n",
CXN_TRANSFER_DATA_LENGTH, iTotalLengthReceived);
}
printf("*INFO* | Received following data string from remote device:\n%s\n", szDataBuffer);
// Close the connection
if ( closesocket(ClientSocket) == SOCKET_ERROR)
{
printf("=CRITICAL= | closesocket() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
}
else
{
// Make the connection invalid regardless
ClientSocket = INVALID_SOCKET;
if ( (2 <= g_iOutputLevel) | (closesocket(ClientSocket) != SOCKET_ERROR) )
{
printf("*INFO* | closesocket() call succeeded w/socket=[0x%X]\n", ClientSocket);
}
}
}
}
CleanupAndExit:
if ( INVALID_SOCKET != ClientSocket )
{
closesocket(ClientSocket);
ClientSocket = INVALID_SOCKET;
}
if ( INVALID_SOCKET != LocalSocket )
{
closesocket(LocalSocket);
LocalSocket = INVALID_SOCKET;
}
if ( NULL != lptstrThisComputerName )
{
HeapFree(GetProcessHeap(), 0, lptstrThisComputerName);
lptstrThisComputerName = NULL;
}
if ( NULL != lpCSAddrInfo )
{
HeapFree(GetProcessHeap(), 0, lpCSAddrInfo);
lpCSAddrInfo = NULL;
}
return ulRetCode;
}
// RunClientMode runs the application in client mode. It opens a socket, connects it to a
// remote socket, transfer some data over the connection and closes the connection.
ULONG RunClientMode(ULONGLONG ululRemoteAddr, int iMaxCxnCycles)
{
ULONG ulRetCode = 0;
int iCxnCount = 0;
char szData[CXN_TRANSFER_DATA_LENGTH] = {0};
SOCKET LocalSocket = INVALID_SOCKET;
SOCKADDR_BTH SockAddrBthServer = {0};
// Setting address family to AF_BTH indicates winsock2 to use Bluetooth sockets
// Port should be set to 0 if ServiceClassId is spesified.
SockAddrBthServer.addressFamily = AF_BTH;
SockAddrBthServer.btAddr = (BTH_ADDR) ululRemoteAddr;
SockAddrBthServer.serviceClassId = g_guidServiceClass;
// Valid ports are 1 - 31
SockAddrBthServer.port = 5;
// Create a static data-string, which will be transferred to the remote Bluetooth device
// may make this #define and do strlen() of the string
strncpy_s(szData, sizeof(szData), "~!@#$%^&*()-_=+?<>1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
CXN_TRANSFER_DATA_LENGTH - 1);
// Run the connection/data-transfer for user specified number of cycles
for ( iCxnCount = 0; (0 == ulRetCode) && (iCxnCount < iMaxCxnCycles || iMaxCxnCycles == 0); iCxnCount++ )
{
printf("\n");
// Open a bluetooth socket using RFCOMM protocol
if ( ( LocalSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | socket() call failed. Error = [%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (LocalSocket != INVALID_SOCKET))
{
printf("*INFO* | socket() call succeeded. Socket = [0x%X]\n", LocalSocket);
}
if ( 1 <= g_iOutputLevel )
{
printf("*INFO* | connect() attempt with Remote BTHAddr = [0x%X]\n", ululRemoteAddr);
}
// Connect the socket (pSocket) to a given remote socket represented by address (pServerAddr)
if ( connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH)) == SOCKET_ERROR)
{
printf("=CRITICAL= | connect() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH)) != SOCKET_ERROR) )
{
printf("*INFO* | connect() call succeeded!\n");
}
// send() call indicates winsock2 to send the given data
// of a specified length over a given connection.
printf("*INFO* | Sending the following data string:\n\t%s\n", szData);
if ( send(LocalSocket, szData, CXN_TRANSFER_DATA_LENGTH, 0) == SOCKET_ERROR)
{
printf("=CRITICAL= | send() call failed w/socket = [0x%X], szData = [%p], dataLen = [%d]. WSAGetLastError=[%d]\n",
LocalSocket, szData, CXN_TRANSFER_DATA_LENGTH, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( 2 <= g_iOutputLevel )
{
printf("*INFO* | send() call succeeded\n");
}
// Close the socket
if ( SOCKET_ERROR == closesocket(LocalSocket) )
{
printf("=CRITICAL= | closesocket() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
LocalSocket = INVALID_SOCKET;
if ( 2 <= g_iOutputLevel )
{
printf("*INFO* | closesocket() call succeeded!");
}
}
CleanupAndExit:
if ( LocalSocket != INVALID_SOCKET)
{
closesocket(LocalSocket);
LocalSocket = INVALID_SOCKET;
}
return ulRetCode;
}
为了简化问题,我用另一个windows应用程序加另一个蓝牙适配器来代替移动设备上的程序及蓝牙模块,来验证我的客户端程序!
我的客户端程序和模拟的服务端程序都是运行在XP SP3上,各有一个USB bluetooth dongle, 服务端和客户端程序如下,服务端能给成功listen, 并阻塞在accept上,客户端程序却一连接就失败!
我又试着在服务端和客户端把BT_PORT_ANY作port的值, 可是还是连不上!
// RunServerMode runs the application in server mode. It opens a socket, connects it to a
// remote socket, transfer some data over the connection and closes the connection.
ULONG RunServerMode(int iMaxCxnCycles)
{
ULONG ulRetCode = 0;
int iAddrLen = sizeof(SOCKADDR_BTH), iCxnCount = 0, iLengthReceived = 0, iTotalLengthReceived = 0;
char szDataBuffer[CXN_TRANSFER_DATA_LENGTH] = {0};
char * pszDataBufferIndex = NULL;
LPTSTR lptstrThisComputerName = NULL;
DWORD dwLenComputerName = MAX_COMPUTERNAME_LENGTH + 1;
SOCKET LocalSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET;
WSAVERSION wsaVersion = {0};
WSAQUERYSET wsaQuerySet = {0};
SOCKADDR_BTH SockAddrBthLocal = {0};
LPCSADDR_INFO lpCSAddrInfo = NULL;
BOOL bContinue;
// Both of these fixed-size allocations can be on the stack
if ( ( lpCSAddrInfo = (LPCSADDR_INFO) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSADDR_INFO) ) ) == NULL)
{
printf("!ERROR! | Unable to allocate memory for CSADDR_INFO\n");
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("HeapAlloc() for CSADDR_INFO (address) is OK!\n");
if ( ( lptstrThisComputerName = (LPTSTR) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwLenComputerName ) ) == NULL)
{
printf("!ERROR! | Unable to allocate memory for CSADDR_INFO\n");
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("HeapAlloc() for CSADDR_INFO (local computer name) is OK!\n");
if ( !GetComputerName(lptstrThisComputerName, &dwLenComputerName) )
{
printf("=CRITICAL= | GetComputerName() call failed. WSAGetLastError=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
{
printf("GetComputerName() is pretty fine!\n");
printf("Local computer name: %S\n", lptstrThisComputerName);
}
// Open a bluetooth socket using RFCOMM protocol
printf("Opening local socket using socket()...\n");
if ( ( LocalSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | socket() call failed. WSAGetLastError = [%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (LocalSocket != INVALID_SOCKET))
{
printf("*INFO* | socket() call succeeded! Socket = [0x%X]\n", LocalSocket);
}
// Setting address family to AF_BTH indicates winsock2 to use Bluetooth port
SockAddrBthLocal.addressFamily = AF_BTH;
// Valid ports are 1 - 31
//SockAddrBthLocal.port = BT_PORT_ANY;
SockAddrBthLocal.port = 5;
// bind() associates a local address and port combination
// with the socket just created. This is most useful when
// the application is a server that has a well-known port
// that clients know about in advance.
if ( bind(LocalSocket, (struct sockaddr *) &SockAddrBthLocal, sizeof(SOCKADDR_BTH) ) == SOCKET_ERROR)
{
printf("=CRITICAL= | bind() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (bind(LocalSocket, (struct sockaddr *) &SockAddrBthLocal, sizeof(SOCKADDR_BTH) ) != SOCKET_ERROR))
{
printf("*INFO* | bind() call succeeded!\n");
}
if ( ( ulRetCode = getsockname(LocalSocket, (struct sockaddr *)&SockAddrBthLocal, &iAddrLen) ) == SOCKET_ERROR)
{
printf("=CRITICAL= | getsockname() call failed w/socket = [0x%X]. WSAGetLastError=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
{
printf("getsockname() is pretty fine!\n");
printf("Local address: 0x%x\n", SockAddrBthLocal.btAddr);
}
// CSADDR_INFO
lpCSAddrInfo[0].LocalAddr.iSockaddrLength = sizeof( SOCKADDR_BTH );
lpCSAddrInfo[0].LocalAddr.lpSockaddr = (LPSOCKADDR)&SockAddrBthLocal;
lpCSAddrInfo[0].RemoteAddr.iSockaddrLength = sizeof( SOCKADDR_BTH );
lpCSAddrInfo[0].RemoteAddr.lpSockaddr = (LPSOCKADDR)&SockAddrBthLocal;
lpCSAddrInfo[0].iSocketType = SOCK_STREAM;
lpCSAddrInfo[0].iProtocol = BTHPROTO_RFCOMM;
// If we got an address, go ahead and advertise it.
ZeroMemory(&wsaQuerySet, sizeof(WSAQUERYSET));
wsaQuerySet.dwSize = sizeof(WSAQUERYSET);
wsaQuerySet.lpServiceClassId = (LPGUID) &g_guidServiceClass;
// should be something like "Sample Bluetooth Server"
wsaQuerySet.lpszServiceInstanceName = lptstrThisComputerName;
wsaQuerySet.lpszComment = L"Example Service instance registered in the directory service through RnR";
wsaQuerySet.dwNameSpace = NS_BTH;
wsaQuerySet.dwNumberOfCsAddrs = 1; // Must be 1.
wsaQuerySet.lpcsaBuffer = lpCSAddrInfo; // Required.
// As long as we use a blocking accept(), we will have a race
// between advertising the service and actually being ready to
// accept connections. If we use non-blocking accept, advertise
// the service after accept has been called.
if ( WSASetService(&wsaQuerySet, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR)
{
printf("=CRITICAL= | WSASetService() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
else
printf("WSASetService() looks fine!\n");
// listen() call indicates winsock2 to listen on a given socket for any incoming connection.
if ( listen(LocalSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("=CRITICAL= | listen() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (listen(LocalSocket, SOMAXCONN) != SOCKET_ERROR))
{
printf("*INFO* | listen() call succeeded!\n");
}
for ( iCxnCount = 0; (0 == ulRetCode) && ( (iCxnCount < iMaxCxnCycles) || (iMaxCxnCycles == 0) ); iCxnCount++ )
{
printf("\n");
// accept() call indicates winsock2 to wait for any
// incoming connection request from a remote socket.
// If there are already some connection requests on the queue,
// then accept() extracts the first request and creates a new socket and
// returns the handle to this newly created socket. This newly created
// socket represents the actual connection that connects the two sockets.
if ( ( ClientSocket = accept(LocalSocket, NULL, NULL) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | accept() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
break; // Break out of the for loop
}
if ( (2 <= g_iOutputLevel) | (ClientSocket != INVALID_SOCKET))
{
printf("*INFO* | accept() call succeeded. CientSocket = [0x%X]\n", ClientSocket);
}
// Read data from the incoming stream
bContinue = TRUE;
pszDataBufferIndex = &szDataBuffer[0];
while ( bContinue && (iTotalLengthReceived < CXN_TRANSFER_DATA_LENGTH) )
{
// recv() call indicates winsock2 to receive data
// of an expected length over a given connection.
// recv() may not be able to get the entire length
// of data at once. In such case the return value,
// which specifies the number of bytes received,
// can be used to calculate how much more data is
// pending and accordingly recv() can be called again.
iLengthReceived = recv(ClientSocket, pszDataBufferIndex, (CXN_TRANSFER_DATA_LENGTH - iTotalLengthReceived), 0);
switch ( iLengthReceived )
{
case 0: // socket connection has been closed gracefully
printf("Socket connection has been closed gracefully!\n");
bContinue = FALSE;
break;
case SOCKET_ERROR:
printf("=CRITICAL= | recv() call failed. Error=[%d]\n", WSAGetLastError());
bContinue = FALSE;
ulRetCode = 1;
break;
default: // most cases when data is being read
pszDataBufferIndex += iLengthReceived;
iTotalLengthReceived += iLengthReceived;
if ( (2 <= g_iOutputLevel) | (iLengthReceived != SOCKET_ERROR))
{
printf("*INFO* | Receiving data of length = [%d]. Current Total = [%d]\n", iLengthReceived, iTotalLengthReceived);
}
break;
}
}
if (ulRetCode == 0)
{
if ( CXN_TRANSFER_DATA_LENGTH != iTotalLengthReceived )
{
printf("+WARNING+ | Data transfer aborted mid-stream. Expected Length = [%d], Actual Length = [%d]\n",
CXN_TRANSFER_DATA_LENGTH, iTotalLengthReceived);
}
printf("*INFO* | Received following data string from remote device:\n%s\n", szDataBuffer);
// Close the connection
if ( closesocket(ClientSocket) == SOCKET_ERROR)
{
printf("=CRITICAL= | closesocket() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
}
else
{
// Make the connection invalid regardless
ClientSocket = INVALID_SOCKET;
if ( (2 <= g_iOutputLevel) | (closesocket(ClientSocket) != SOCKET_ERROR) )
{
printf("*INFO* | closesocket() call succeeded w/socket=[0x%X]\n", ClientSocket);
}
}
}
}
CleanupAndExit:
if ( INVALID_SOCKET != ClientSocket )
{
closesocket(ClientSocket);
ClientSocket = INVALID_SOCKET;
}
if ( INVALID_SOCKET != LocalSocket )
{
closesocket(LocalSocket);
LocalSocket = INVALID_SOCKET;
}
if ( NULL != lptstrThisComputerName )
{
HeapFree(GetProcessHeap(), 0, lptstrThisComputerName);
lptstrThisComputerName = NULL;
}
if ( NULL != lpCSAddrInfo )
{
HeapFree(GetProcessHeap(), 0, lpCSAddrInfo);
lpCSAddrInfo = NULL;
}
return ulRetCode;
}
// RunClientMode runs the application in client mode. It opens a socket, connects it to a
// remote socket, transfer some data over the connection and closes the connection.
ULONG RunClientMode(ULONGLONG ululRemoteAddr, int iMaxCxnCycles)
{
ULONG ulRetCode = 0;
int iCxnCount = 0;
char szData[CXN_TRANSFER_DATA_LENGTH] = {0};
SOCKET LocalSocket = INVALID_SOCKET;
SOCKADDR_BTH SockAddrBthServer = {0};
// Setting address family to AF_BTH indicates winsock2 to use Bluetooth sockets
// Port should be set to 0 if ServiceClassId is spesified.
SockAddrBthServer.addressFamily = AF_BTH;
SockAddrBthServer.btAddr = (BTH_ADDR) ululRemoteAddr;
SockAddrBthServer.serviceClassId = g_guidServiceClass;
// Valid ports are 1 - 31
SockAddrBthServer.port = 5;
// Create a static data-string, which will be transferred to the remote Bluetooth device
// may make this #define and do strlen() of the string
strncpy_s(szData, sizeof(szData), "~!@#$%^&*()-_=+?<>1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
CXN_TRANSFER_DATA_LENGTH - 1);
// Run the connection/data-transfer for user specified number of cycles
for ( iCxnCount = 0; (0 == ulRetCode) && (iCxnCount < iMaxCxnCycles || iMaxCxnCycles == 0); iCxnCount++ )
{
printf("\n");
// Open a bluetooth socket using RFCOMM protocol
if ( ( LocalSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM) ) == INVALID_SOCKET)
{
printf("=CRITICAL= | socket() call failed. Error = [%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (LocalSocket != INVALID_SOCKET))
{
printf("*INFO* | socket() call succeeded. Socket = [0x%X]\n", LocalSocket);
}
if ( 1 <= g_iOutputLevel )
{
printf("*INFO* | connect() attempt with Remote BTHAddr = [0x%X]\n", ululRemoteAddr);
}
// Connect the socket (pSocket) to a given remote socket represented by address (pServerAddr)
if ( connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH)) == SOCKET_ERROR)
{
printf("=CRITICAL= | connect() call failed. Error=[%d]\n", WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( (2 <= g_iOutputLevel) | (connect(LocalSocket, (struct sockaddr *) &SockAddrBthServer, sizeof(SOCKADDR_BTH)) != SOCKET_ERROR) )
{
printf("*INFO* | connect() call succeeded!\n");
}
// send() call indicates winsock2 to send the given data
// of a specified length over a given connection.
printf("*INFO* | Sending the following data string:\n\t%s\n", szData);
if ( send(LocalSocket, szData, CXN_TRANSFER_DATA_LENGTH, 0) == SOCKET_ERROR)
{
printf("=CRITICAL= | send() call failed w/socket = [0x%X], szData = [%p], dataLen = [%d]. WSAGetLastError=[%d]\n",
LocalSocket, szData, CXN_TRANSFER_DATA_LENGTH, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
if ( 2 <= g_iOutputLevel )
{
printf("*INFO* | send() call succeeded\n");
}
// Close the socket
if ( SOCKET_ERROR == closesocket(LocalSocket) )
{
printf("=CRITICAL= | closesocket() call failed w/socket = [0x%X]. Error=[%d]\n", LocalSocket, WSAGetLastError());
ulRetCode = 1;
goto CleanupAndExit;
}
LocalSocket = INVALID_SOCKET;
if ( 2 <= g_iOutputLevel )
{
printf("*INFO* | closesocket() call succeeded!");
}
}
CleanupAndExit:
if ( LocalSocket != INVALID_SOCKET)
{
closesocket(LocalSocket);
LocalSocket = INVALID_SOCKET;
}
return ulRetCode;
}
我自己来说说我这两天尝试解决上述问题的结果。
先是把上面的基于windows socket的程序反复试了又试,总是连接失败,网上的资料虽然不少,就是没有sample code, msdn的sample code说在%_WINCEROOT%\Public\Common\Oak\Drivers\Bluetooth\Sample\Ssa, 可是我把smartphone 2003 SDK安装上,又装了个Embedded Visual C++ 4.0, sample里面也只有一个sdpsearch, 真不知道MS是不是故意把他拿掉了
再是在bluesoleil上当了个SDK,discovery, connect都有,可是数据传输上不太满意,大把的ftp, opp, audio, video之类的东西,可是,偏偏没有最最基本的send, recv来实现二进制数据流的发送、接收。因为我们将来server端的程序会运行在不同平台上的移动设备上,server端的程序怎么解析这些命令呢?
明天等bluesoleil的技术支持的回复了,这个事情已经拖了两天了,sign, 微软对bluetooth的支持为什么这么差呢?为什么不能像wifi那么简单,那么透明,msdn上的sample code一运行,十分钟搞定?