下载并编译完alljoyn-14.06源码后,在buildwin7x86debugdistcppsamples下生成了了些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 sizen");
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:%dn",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(&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:%dn",size);
} else {
//图片发完了
if (outputStream == NULL) {
printf("The file received okn");
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;
}
}
如此一来,分别启动,就能传输了。效果截图:
当然还可以做进一步的优化,比如做成界面或者一对多传输、多对多传输形式等等
|