码迷,mamicode.com
首页 > 其他好文 > 详细

【AllJoyn框架-09】AllJoyn 局域网文件传输(修改官方版本)

时间:2015-04-21 18:02:12      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:alljoyn

下载并编译完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;
        }
    }

如此一来,分别启动,就能传输了。效果截图:

技术分享

当然还可以做进一步的优化,比如做成界面或者一对多传输、多对多传输形式等等

【AllJoyn框架-09】AllJoyn 局域网文件传输(修改官方版本)

标签:alljoyn

原文地址:http://blog.csdn.net/baiwfg2/article/details/45173673

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!