首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

蓝牙socket的recv()有关问题

2012-03-06 
蓝牙socket的recv()问题 - C++ Builder / Windows SDK/API在Windows Mobile6.1系统上做蓝牙,使用socket。现

蓝牙socket的recv()问题 - C++ Builder / Windows SDK/API
在Windows Mobile6.1系统上做蓝牙,使用socket。
现在搜索、连接、发送都没有问题。接收用的是recv()堵塞,现在的情况是:能收到数据,但每次收几个字节就通知我,完整的一帧(自定义的)要分好多次才能收完。例如发送1234567890,会先收一个字节“1”,再收“234567”,再收“890”这样。
想请教一下,是不是什么参数我没有设置?堵塞接收怎样才能一次接收成功完整的一帧?
源码如下:[code=C/C++][/code]

//
#include <Bt_api.h.>
#include <winioctl.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define lengthof(exp) ((sizeof((exp)))/sizeof((*(exp))))
#define IOCTL_SERVICE_STARTCTL_CODE(FILE_DEVICE_SERVICE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SERVICE_STOPCTL_CODE(FILE_DEVICE_SERVICE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SERVICE_REFRESHCTL_CODE(FILE_DEVICE_SERVICE, 3, METHOD_BUFFERED, FILE_ANY_ACCESS)

//////////////////////////////////////////////////////////////////////////
//


GUID RFCOMM_PROTOCOL_UUID = {0x00001101, 0x0000, 0x1000, {0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}};

HKEY m_hKey;
//
HWND m_hwnd_List_Find;
TCHAR wRbuf[64];
//
#define NS_BTH 16
//
#define MAX_NAME 248

//


//
SOCKET m_socket;
//
//
LPWSAQUERYSET pwsaResults;
//
CStringArray csar;
unsigned short g_port;


UINT m_LinkState;//连接活动进行到什么状态
#define DEFAULT_PORT 1

//保存蓝牙设备 BT_ADDR
CArray<BT_ADDR, BT_ADDR> arb;


HWNDhWnd;
BOOLnExit = FALSE;
HANDLEhThread = INVALID_HANDLE_VALUE;
staticDWORD WINAPI ReadThread( PVOID pArg );

IMPLEMENT_DYNCREATE(CBthOpe4View, CFormView)

BEGIN_MESSAGE_MAP(CBthOpe4View, CFormView)
ON_BN_CLICKED(IDC_BUT_FIND, &CBthOpe4View::OnBnClickedButFind)
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_BUT_LINK, &CBthOpe4View::OnBnClickedButLink)
ON_BN_CLICKED(IDC_BTN_SEND, &CBthOpe4View::OnBnClickedBtnSend)
ON_WM_TIMER()
END_MESSAGE_MAP()

// CBthOpe4View 构造/析构

CBthOpe4View::CBthOpe4View()
: CFormView(CBthOpe4View::IDD)
{
// TODO: 在此处添加构造代码

}

CBthOpe4View::~CBthOpe4View()
{
}

void CBthOpe4View::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
}

BOOL CBthOpe4View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式

return CFormView::PreCreateWindow(cs);
}



void CBthOpe4View::OnInitialUpdate()
{
CFormView::OnInitialUpdate();

m_LinkState = 0;
SetTimer(1,100,NULL);

GetDlgItem( IDC_LIST_FIND, &m_hwnd_List_Find );
WSADATA wsd;
int ret = WSAStartup( MAKEWORD( 2, 2 ), &wsd );
WCHAR *argPtr = _T("card");
 HANDLE hDev = CreateFile (L"BTD0:", GENERIC_READ | GENERIC_WRITE,//打开电源
 FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING, 0, NULL);
 
 if (hDev != INVALID_HANDLE_VALUE) 
 {
 int iErr = DeviceIoControl (hDev, IOCTL_SERVICE_START, argPtr, sizeof(WCHAR) * (wcslen (argPtr) + 1), NULL, NULL, NULL, NULL);
 CloseHandle (hDev);
 }

nExit = TRUE;
hThread = CreateThread(NULL,0, ReadThread,NULL, 0,NULL);

Sleep(1000);
}


// CBthOpe4View 诊断

#ifdef _DEBUG
void CBthOpe4View::AssertValid() const
{
CFormView::AssertValid();
}

CBthOpe4Doc* CBthOpe4View::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBthOpe4Doc)));
return (CBthOpe4Doc*)m_pDocument;
}
#endif //_DEBUG


// CBthOpe4View 消息处理程序

void CBthOpe4View::OnBnClickedButFind()
{
// TODO: 在此添加控件通知处理程序代码
if ( TRUE == m_BSoketFlag ) 
{
m_BSoketFlag = FALSE;
closesocket( m_socket );
}

((CListBox*)GetDlgItem(IDC_LIST_FIND))->ResetContent();



GetDlgItem(IDC_BUT_FIND)->EnableWindow( FALSE );
PerformInquiry();
GetDlgItem(IDC_BUT_FIND)->EnableWindow( TRUE );
}
//////////////////////////////////////////////////////////////////////////
BOOL CBthOpe4View::Open( )
{
unsigned int channel = 0;

//创建TCP套接字 
m_socket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (m_socket == INVALID_SOCKET)
return FALSE;

  return TRUE;
}
//查询蓝牙设备
BOOL CBthOpe4View::PerformInquiry() 
{
int ret ;
int count = 0;
int retry = 0 ;

arb.RemoveAll();
csar.RemoveAll();

WSAQUERYSET wsaq;
HANDLE hLookup;
union {
CHAR buf[5000];
double __unused; // ensure proper alignment
};

Open();

/*LPWSAQUERYSET*/ pwsaResults = (LPWSAQUERYSET) buf;
DWORD dwSize = sizeof(buf);
BOOL bHaveName;
//搜索其它蓝牙设备

ZeroMemory(&wsaq, sizeof(wsaq));
wsaq.dwSize = sizeof(wsaq);
wsaq.dwNameSpace = NS_BTH;
wsaq.lpcsaBuffer = NULL;

ret = WSALookupServiceBegin(&wsaq, LUP_CONTAINERS, &hLookup);
if(ERROR_SUCCESS != ret)
{
wprintf(L"WSALookupServiceBegin failed %d\r\n", GetLastError());
return FALSE;


ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
while (1)
{
ret = WSALookupServiceNext(hLookup, 
LUP_RETURN_NAME | LUP_RETURN_ADDR, 
&dwSize, pwsaResults);
if(ret != ERROR_SUCCESS)
{
ret = WSAGetLastError();
break;
}

ASSERT (pwsaResults->dwNumberOfCsAddrs == 1);
BT_ADDR b = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;

g_port = ((sockaddr_in*)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->sin_port;
//if(g_port == 0)
g_port = DEFAULT_PORT;

bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
// for test
arb.Add( b );
WCHAR szDevice[MAX_NAME+25];
wsprintf (szDevice, L"%s%s%04x%08x%s", bHaveName ? pwsaResults->lpszServiceInstanceName : L"", 
bHaveName ? L"(" : L"", GET_NAP(b), GET_SAP(b), bHaveName ? L")" : L"");

CString csDevice = szDevice;
// for test
csar.Add( csDevice );
ListBox_AddString( m_hwnd_List_Find, csDevice);
//MessageBox(csDevice);

count ++ ;
}
WSALookupServiceEnd(hLookup);

if(!count)
{
AfxMessageBox(_T("搜索失败"));
return FALSE ;
}
return TRUE;
}


[解决办法]
他本身就是流式协议,每次接受字节数不定,需要自己判断是否接收完整。

热点排行