微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > 通过USB蓝牙适配器连接server端程序失败!?

通过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 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一运行,十分钟搞定?

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top