indy10下以字节形式发送结构无法收到

blacktulipg 2010-12-22 02:05:59
客户端以字节数组形式发送一个结构以后,服务器无法正确读出内容,不知道问题出在哪里


客户端发送
userInfo aUser;
aUser.name=Edit1->Text;
aUser.passWord=Edit2->Text;

TBytes buffer;
buffer=RawToBytes(&aUser, sizeof(userInfo));
IdTCPClient1->IOHandler->Write(buffer);

服务器端接收
userInfo aUser;
TBytes buffer;
try
{
AContext->Connection->IOHandler->ReadBytes(buffer, sizeof(userInfo), false);
BytesToRaw(buffer, &aUser, sizeof(userInfo));
Memo1->Lines->Add("用户名:"+aUser.name);
Memo1->Lines->Add("密码:"+aUser.passWord);
}
catch (Exception &e)
{
Memo1->Lines->Add("读取登录信息异常");
return;
}
...全文
338 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
blacktulipg 2010-12-28
  • 打赏
  • 举报
回复
使用WideChar的结构也可以使用周药师的代码
struct UniComuniText
{
WideChar name[10];
WideChar password[10];
WideChar word[200];
};

UniComuniText aUniComuniText;
wcscpy(aUniComuniText.name, Edit1->Text.c_str());
wcscpy(aUniComuniText.password, Edit2->Text.c_str());
wcscpy(aUniComuniText.word, Edit3->Text.c_str());

客户端发送
try
{
buffer=RawToBytes(&aUniComuniText, sizeof(UniComuniText));
IdTCPClient1->IOHandler->Write(buffer);
}
catch (Exception &e)
{
Memo1->Lines->Add("发送失败");
}


服务器端接收
try
{
AContext->Connection->IOHandler->ReadBytes(buffer, sizeof(UniComuniText), false);
BytesToRaw(buffer, &aUniComuniText, sizeof(UniComuniText));
}
catch (Exception &e)
{

}
blacktulipg 2010-12-27
  • 打赏
  • 举报
回复
在BCB2010下面一切正常,周药师的代码可以直接拷贝使用
huigezi123 2010-12-24
  • 打赏
  • 举报
回复
我用2007试过了可以收到,如果楼主编译时有问题的话我个人猜想这几句代码的位置可能有些问题,因为你的代码里没有,所以只是猜测:
IdTCPClient1->Port = 8000;
IdTCPClient1->Host = "127.0.0.1";
IdTCPClient1->Connect();
blacktulipg 2010-12-24
  • 打赏
  • 举报
回复
我的bcb2007用asc码。
以下代码可以正确运行
//测试数据与字节数组互写
userInfo aUser, bUser;
aUser.name="张三";
aUser.passWord="hppqqw";
TBytes buffer;
buffer=RawToBytes(&aUser, sizeof(userInfo));
int l=buffer.get_length();
Memo1->Lines->Add("buffer长度为"+IntToStr(l));
Memo1->Lines->Add("userInfo长度为"+IntToStr(sizeof(userInfo)));
BytesToRaw(buffer, &bUser, sizeof(userInfo));
Memo1->Lines->Add("用户名:"+bUser.name);
Memo1->Lines->Add("密码:"+bUser.passWord);
周药师 2010-12-23
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 blacktulipg 的回复:]

好的,我试试看,但是我要通过字节数组发送流能够做到吗,还是通过设定一个固定长度的字节数组,然后封装成结构。例如:
struct sendStruct
{
char array[128];
}

然后把内存流写入char array[128],这样是一个可以用的方案吧
[/Quote]
当然可以
跟我给你的差不多
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
好的,我试试看,但是我要通过字节数组发送流能够做到吗,还是通过设定一个固定长度的字节数组,然后封装成结构。例如:
struct sendStruct
{
char array[128];
}

然后把内存流写入char array[128],这样是一个可以用的方案吧
周药师 2010-12-23
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 blacktulipg 的回复:]

可以用BCB2010尝试我的代码吗
[/Quote]
不需要试了
你把结构体的 变量的类型定义 改成我的那样
就可以把我的代码直接套用了 ,
周药师 2010-12-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 blacktulipg 的回复:]

AnsiString是定长变量,我尝试过sizeof,长度读出来一样
[/Quote]
考虑到结构体内存字节对齐问题
建议你不要用AnsiString、String 之类的
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
可以用BCB2010尝试我的代码吗
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
RawToBytes和BytesToRaw我分别用内存流试过,一点问题没有,内存流内写入的就是我那些结构,但是一旦发送问题就来了
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
AnsiString是定长变量,我尝试过sizeof,长度读出来一样
周药师 2010-12-23
  • 打赏
  • 举报
回复
“//发送内容结构
struct userInfo//用户
{
AnsiString name;
AnsiString passWord;
};”

还是建议你结构体内 用定长的变量 改成
struct userInfo
{
TCHAR name[20];
TCHAR passWord[20] ;
};

我这里没有CB2007 无法给你测试

你用我的代码有问题吗?
周药师 2010-12-23
  • 打赏
  • 举报
回复
我这里没有2007 无法帮你试 谁有环境谁来帮你吧
有一点你注意一下在2009、2010、2011里用的是Unicode 低版本的(包括2007)是ASCII
你解析不对
一则可能是是编码的问题
另外的检查一下你的解析方法是不是有隐患?
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
我用的是BCB2007
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
好的,我把我打算发送的数据类型发给你。
目标是把记录了发送内容的内存流以字节形式发送。虽然发送流的方法已经摸好,但是直接以流的形式发送不触发disconnect不会结束流传送,那样就只能以异步通讯形式工作。
以下是生成内存流并从流中读出的函数,经过CRC16检验。
头文件
//---------------------------------------------------------------------------

#ifndef U_ComuniContentH
#define U_ComuniContentH

#include <Classes.hpp>
#include "Contnrs.hpp"//定义TList类
#include "U_CRC16.h"//定义CRC16检验有关函数
//---------------------------------------------------------------------------
//命令字对照表
#define _Arrive 'A'
#define _Leave 'B'
#define _Connect 'C'
#define _Disconnect 'D'
#define _Accept 'E'
#define _Refuse 'F'
#define _Sendto 'G'
#define _Sendfileto 'H'
#define _SuccessToReceive 'I'
#define _FailToReceive 'J'
//---------------------------------------------------------------------------
//发送内容结构
struct userInfo//用户
{
AnsiString name;
AnsiString passWord;
};

struct pCInfo//本机
{
AnsiString pCName;
AnsiString pCIP;
int port;
};

struct command//命令
{
char commandC;//用1个字符代表命令,查阅本文件中的Define表
AnsiString receiver1;//接受者,要执行接收的命令
AnsiString receiver2;//接受者,发送给某个客户端时使用
AnsiString word;//发送的谈话内容
};

struct comuniContent//发送的信息
{
AnsiString SN;//唯一标识符
userInfo user;
pCInfo host;
command aCommand;
};
//---------------------------------------------------------------------------
//从内存流读写comuniContent结构
bool writeComuniContentIntoMemoryStream//将comuniContent写入内存流
(comuniContent *aComuniContent, TMemoryStream *aMemoryStream,
char endC='|', bool calCRC=false, AnsiString *runS="OK");
//endC是结构写入内存以后的末尾加上的结束标识,calCRC为true表示要做CRC计算
bool readComuniContentFromMemoryStream//从内存流读出ComuniContent结构
(comuniContent *aComuniContent, TMemoryStream *aMemoryStream, bool *is,
char endC='|', bool checkCRC=false, AnsiString *runS="OK");
//aComuniContent记录从内存中读出的结构
//endC是结构写入内存以后的结束标识,checkCRC为true表示要做CRC检验
//---------------------------------------------------------------------------
//从字符数组读写内存流
bool writeMemoryStreamIntoCharArray//将内存流写入字符数组
(TMemoryStream *aMemoryStream, char *c, int size=22,
char beginC='~', AnsiString *runS="OK");
//aMemoryStream是内存流指针,c是字符数组首地址
//size是字符数组长度,不能小于内存流长度+2
//beginC写入字符数组时标识起始字符
bool readMemoryStreamFromCharArray//从字符数组读出内存流
(TMemoryStream *aMemoryStream, char *c, int size=22,
char beginC='~', AnsiString *runS="OK");
//aMemoryStream是内存流指针,c是字符数组首地址
//size是字符数组长度,不能小于内存流长度+2
//beginC写入字符数组时标识起始字符
//---------------------------------------------------------------------------
//通过类统一管理comuniContent
class Record: public TObject//本是结构,改写成供TList统一管理的对象
{
public:
comuniContent recordContent;
TDateTime oprateTime;//操作发生的系统时间,为长浮点
};

class RecordsManager//记录交流内容的类
{
protected:
TObjectList *records;//用于管理Record
public:
RecordsManager();
~RecordsManager();
bool addARecord//添加一条记录
(comuniContent aComuniContent, AnsiString *runS="OK");
bool getARecord//读取一条记录,SN即comuniContent.SN
(comuniContent *aComuniContent, AnsiString SN, AnsiString *runS="OK");
bool deleteARecord//删除一条记录,SN即comuniContent.SN
(AnsiString SN, AnsiString *runS="OK");
bool getFirstRecordAndDelete//读取第一条记录并删除此记录
(comuniContent *aComuniContent, AnsiString *runS="OK");
};
//---------------------------------------------------------------------------
#endif
单元文件
//---------------------------------------------------------------------------


#pragma hdrstop

#include "U_ComuniContent.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)

//---------------------------------------------------------------------------
//从内存流读写comuniContent结构函数实现
bool writeComuniContentIntoMemoryStream
(comuniContent *aComuniContent, TMemoryStream *aMemoryStream,
char endC, bool calCRC, AnsiString *runS)
//将comuniContent写入内存流
//endC是结构写入内存以后的末尾加上的结束标识,calCRC为true表示要做CRC计算
{
if ((aComuniContent==NULL)||(aMemoryStream==NULL))
{
*runS="Inputed parameter is invalid";
return false;
}

const int length=sizeof(*aComuniContent)+3;
//sizeof用于类型名或相应变量本程序可以正确运行,用于变量指针则不行
char c[length];

memcpy(c, aComuniContent, sizeof(*aComuniContent));//将结构写入字符数组
if (calCRC==false)//不做CRC计算直接写入内存流
{
c[length-3]=endC;
aMemoryStream->Write(c, length-2);
}
else//需要计算CRC
{
bool b;
b=getCRC16CharArray(c, length);//计算CRC代码,函数默认3位预留字符
if (b==false)
{
*runS="An error in calculating CRC";
return false;
}
c[length-1]=endC;
aMemoryStream->Write(c, length);
}

return true;
}

bool readComuniContentFromMemoryStream
(comuniContent *aComuniContent, TMemoryStream *aMemoryStream, bool *is,
char endC, bool checkCRC, AnsiString *runS)
//从内存流读出ComuniContent结构
//aComuniContent记录从内存中读出的结构
//endC是结构写入内存以后的结束标识,checkCRC为true表示要做CRC检验
{
if ((aComuniContent==NULL)||(aMemoryStream==NULL))
{
*runS="Inputed parameter is invalid";
return false;
}

aMemoryStream->Seek(0, 0);//内存流中记载数据的内存指针到起始位置
//假定接收端不知道内存流中字符数组长度,找到结束标识符后写入新的字符数组
int count=1;
char *pC=(char*)(aMemoryStream->Memory);//取内存流数据存储部分地址
while ((*pC)!=endC)
{
pC++;
count++;//通过自加计算有多少位字符
}

pC=(char*)(aMemoryStream->Memory);//指针移动到内存流数据存储部分地址首位

if (checkCRC==true)
{
bool b;
b=isCrc16Good(is, pC, count);
if (b==false)
{
*runS="An error in checking CRC";
return false;
}

//无论是否通过CRC检验都把内存流中的内容读出
pC=(char*)(aMemoryStream->Memory);
memcpy(aComuniContent, pC, count-3);//减3的原因是默认预留数组有3位保留
}
else
{
memcpy(aComuniContent, pC, count-1);//减1的原因去除结束标识
}

return true;
}
//---------------------------------------------------------------------------
//从字符数组读写内存流
bool writeMemoryStreamIntoCharArray//将内存流写入字符数组
(TMemoryStream *aMemoryStream, char *c, int size,
char beginC, AnsiString *runS)
//aMemoryStream是内存流指针,c是字符数组首地址
//size是字符数组长度,不能小于内存流长度+2
//beginC写入字符数组时标识起始字符
{
if (size<22)
{
*runS="The char array is too short to record memorystream.";
return false;
}

memset(c, 0, size);//字符数组清0
try
{
*c=beginC;
c++;
memcpy(c, aMemoryStream, sizeof(TMemoryStream));
}
catch (Exception &e)
{
*runS="there is an exception.";
return false;
}

return true;
}

bool readMemoryStreamFromCharArray//从字符数组读出内存流
(TMemoryStream *aMemoryStream, char *c, int size,
char beginC, AnsiString *runS)
//aMemoryStream是内存流指针,c是字符数组首地址
//size是字符数组长度,不能小于内存流长度+2
//beginC写入字符数组时标识起始字符
{
if (size<22)
{
*runS="The char array is too short to record memorystream.";
return false;
}

try
{
int i=0;
while (i<size)
{
if (*c==beginC)
break;
c++;
i++;
}

if (*c!=beginC)
{
*runS="Can not find the begin of the memorystream.";
return false;
}
c++;
memcpy(aMemoryStream, c, sizeof(TMemoryStream));
}
catch (Exception &e)
{
*runS="there is an exception.";
return false;
}

return true;
}
//--------------------------------------------------------------------------
//RecordsManager类实现函数
RecordsManager::RecordsManager()
{
records=new TObjectList();
}

RecordsManager::~RecordsManager()
{
records->Clear();
delete records;
}

bool RecordsManager::addARecord //添加一条记录
(comuniContent aComuniContent, AnsiString *runS)
{
if (records==NULL)
{
*runS="TObjectList is error.";
return false;
}

if (&aComuniContent==NULL)
{
*runS="Inputed parameter is invalid.";
return false;
}

Record *record=new Record();
record->recordContent=aComuniContent;
record->oprateTime=0;//初始时间定为12/30/1899 12:00 am
records->Add(record);

return true;
}

bool RecordsManager::getARecord//读取一条记录,SN即comuniContent.SN
(comuniContent *aComuniContent, AnsiString SN, AnsiString *runS)
{
if (records==NULL)
{
*runS="TObjectList is error.";
return false;
}

if (&aComuniContent==NULL)
{
*runS="Inputed parameter is invalid.";
return false;
}

bool b=false;
for (int i=0; i<(records->Count); i++)
{
Record *record=(Record*)(records->Items[i]);
if (SN==record->recordContent.SN)
{
(*aComuniContent)=record->recordContent;
b=true;
break;
}
}

if (b==false)
{
*runS="No match record.";
return false;//如果没有符合要求的记录也返回false
}

return true;
}

bool RecordsManager::deleteARecord//删除一条记录,SN即comuniContent.SN
(AnsiString SN, AnsiString *runS)
{
if (records==NULL)
{
*runS="TObjectList is error.";
return false;
}

if (records->Count==0)
{
*runS="No record in list.";
return false;
}

bool b=false;
for (int i=0; i<(records->Count); i++)
{
Record *record=(Record*)(records->Items[i]);
if (SN==record->recordContent.SN)
{
records->Delete(i);
b=true;
break;
}
}

if (b==false)
{
*runS="No match record.";
return false;//如果没有符合要求的记录也返回false
}

return true;
}

bool RecordsManager::getFirstRecordAndDelete//读取第一条记录并删除此记录
(comuniContent *aComuniContent, AnsiString *runS)
{
if (records==NULL)
{
*runS="TObjectList is error.";
return false;
}

if (records->Count==0)
{
*runS="No record in list.";
return false;
}

Record *record=(Record*)(records->Items[0]);
(*aComuniContent)=record->recordContent;
records->Delete(0);

return true;
}
//---------------------------------------------------------------------------
周药师 2010-12-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 blacktulipg 的回复:]

我的代码和周药师很相似,除了我使用AnsiString以外,但是不知道为什么不能收到。
RawToBytes和BytesToRaw我分别试过,一切都好。发送的字节也已用char方式读出,分别对的上号,但是就是工作不正常。
[/Quote]
我的代码是测试通过的,你可以直接用

如果你不用我的代码 你把你的结构体发出来看看,看看里面变量是什么类型的? 我再用你的结构体去调试一下
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
我的代码和周药师很相似,除了我使用AnsiString以外,但是不知道为什么不能收到。
RawToBytes和BytesToRaw我分别试过,一切都好。发送的字节也已用char方式读出,分别对的上号,但是就是工作不正常。
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
我试了
struct userInfo
{
char name[20];
char passWord[20] ;
};
还是不行,我是indy10.1
周药师 2010-12-23
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 blacktulipg 的回复:]

尝试用了周药师的方法发送和接收以下结构,和用AnsiString的结果一样
struct user
{
char name[10];
char password[20];
} auser;
[/Quote]
我把我3楼代码中的结构体改成了下面的(其余的不变)
struct userInfo
{
char name[20];
char passWord[20] ;
};

我这里依然能够正常发送接收

你用的是CB2007 可能是CB2007和2010中indy版本不同吧?
blacktulipg 2010-12-23
  • 打赏
  • 举报
回复
尝试用了周药师的方法发送和接收以下结构,和用AnsiString的结果一样
struct user
{
char name[10];
char password[20];
} auser;
加载更多回复(5)
内容概要:本文围绕“单相逆变器闭环逆变电路PWM模型仿真研究”展开,基于Simulink平台构建单相逆变器的闭环控制系统仿真模型,重点研究PWM调制技术在逆变电路中的应用与实现。文中详细阐述了系统架构设计、电压电流双闭环控制策略的实现原理、控制器参数设计及仿真建模全过程,并通过仿真结果验证了控制方案在动态响应、稳态精度与系统稳定性方面的有效性。同时,文档还涵盖多种电力电子系统典型应用场景,如多类型短路故障仿真(中性点不接地、经小电阻接地、经消弧线圈接地等)、软开关技术、微电网能量管理、MPPT控制等,体现出较强的技术综合性和工程实践价值。; 适合人群:电气工程、自动化、电力电子与新能源等相关专业的高校本科生、研究生、科研人员,以及从事电力系统仿真、逆变器设计与新能源并网技术研发的工程技术人员。; 使用场景及目标:①掌握基于Simulink的单相逆变器闭环控制系统建模与PWM仿真方法;②深入理解双闭环控制、SPWM/SVPWM调制、系统稳定性分析等核心技术原理;③为课程设计、毕业设计、科研项目或实际工程开发提供可复用的仿真模型与技术支持; 阅读建议:建议结合文中仿真模型动手实践,重点掌握PI控制器参数整定、PWM信号生成机制与仿真结果分析方法,同时可延伸学习文档中涉及的软开关、故障仿真、微电网控制等关联技术,以拓展系统级设计能力。

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧