下载并编译完alljoyn-14.06源码后,在\build\win7\x86\debug\dist\cpp\samples下生成了了些alljoyn实例,其中就有一个与文件传输有关的FileTransfer。但也许是官方版本有bug(我也确实看到了bug),运行时总是异常,客户端无法收到文件。于是就有了这个修改版,可以实现文件传输了。并且传输方向我更换了,客户端向服务端循环发送文件,服务端等待接收即可。下面是核心实现过程。
客户端
1、创建一接收图片信号,附带两个参数,文件名和字节数组
fileTransferInterface->AddSignal("FileTransfer", "say", "name,data", 0, 0);
2、客户端的main中,接入会话后,循环发送图片即可
if (ER_OK == status) { while (1) { busObject.FileTransfer(argv[1]); Sleep(4000); } }
3、传输文件的方法实现
void FileTransfer(const char *filename) { char* buf = new char[ALLJOYN_MAX_ARRAY_LEN]; memset(buf,0,ALLJOYN_MAX_ARRAY_LEN);//官方版本并没有把buf清零,较危险 long l,length,len; ifstream inputStream(filename, ios::in | ios::binary); if (inputStream.is_open()) { MsgArg args[2]; QStatus status = ER_OK; const uint8_t flags = ALLJOYN_FLAG_GLOBAL_BROADCAST; l=inputStream.tellg(); inputStream.seekg(0,ios::end); length=inputStream.tellg(); len = length; //在这里我限定了文件大小,最大为1M if (len > 1024 * 1024){ printf("too big image size\n"); exit(-1); } inputStream.seekg(0); while (len > 0) { //如果图片超过alljoyn规定的数组最大长度,得分块传 long bufferLength = ALLJOYN_MAX_ARRAY_LEN; if (len > (filebuf::pos_type)ALLJOYN_MAX_ARRAY_LEN) { len -= (filebuf::pos_type)ALLJOYN_MAX_ARRAY_LEN; } else { bufferLength = len; len = 0; } inputStream.read(buf, bufferLength); args[0].Set("s", filename); args[1].Set("ay", bufferLength, buf); status = Signal(NULL, s_sessionId, *picDataSigMember, args, 2, 0, flags); } //最后一次传输标识图片传输结束,方便对方检测 args[0].Set("s", filename); args[1].Set("ay", 0, NULL); status = Signal(NULL, s_sessionId, *picDataSigMember, args, 2, 0, flags); printf("sent %s ok. size:%d\n",filename,length); } else { printf("The file doesn't exist or the permissions is stopping the app from opening the file.\n"); } }
服务端
1、创建相同的图片信号,并添加信号处理方法
fileTransferInterface->AddSignal("FileTransfer", "say", "name,data", 0, 0); status = s_msgBus->RegisterSignalHandler(this, static_cast<MessageReceiver::SignalHandler>(&FileTransferObject::FileTransferSignalHandler), picDataSigMember, NULL);
2、main主线程休眠;信号处理方法实现如下:
void FileTransferSignalHandler(const InterfaceDescription::Member* member,const char* sourcePath, Message& msg) { //这个实现我改得较多,没有分块数,且不用每次都解析文件名 uint8_t* data; size_t size; static unsigned int offset = 0; msg->GetArg(1)->Get("ay", &size, &data); if (size != 0) { //pData是动态分配的,大小即是我规定的最大大小 memcpy(pData+offset,data,size); offset += size; printf("rece size:%d\n",size); } else { //图片发完了 if (outputStream == NULL) { printf("The file received ok\n"); char* filePathAndName; msg->GetArg(0)->Get("s", &filePathAndName); //解析文件名 char *fileName = filePathAndName; char* fileNameBack = strrchr(filePathAndName, '\\'); char* fileNameForward = strrchr(filePathAndName, '/'); if (fileNameBack && fileNameForward) { fileName = (fileNameBack > fileNameForward ? fileNameBack : fileNameForward) + 1; } else { if (fileNameForward) { fileName = fileNameForward + 1; } if (fileNameBack) { fileName = fileNameBack + 1; } } printf("opening the output stream to write file '%s'.\n", fileName); outputStream = new ofstream(fileName, ios::out | ios::binary); //字节流写入文件 outputStream->write(pData,offset); offset = 0;//务必清零 } delete outputStream; outputStream = NULL; } }
如此一来,分别启动,就能传输了。效果截图:
当然还可以做进一步的优化,比如做成界面或者一对多传输、多对多传输形式等等
时间: 2024-11-07 16:35:37