用idtcpclient和服務器通訊會出現“connection closed gracefully”,基本流程是客戶端向服務器發資料,服務器執行完操作后將資料回傳。
求大神幫忙分析下,原始碼如下:
void __fastcall TfmTimerReadOne::Timer2Timer(TObject *Sender)
{
byte Recive_Datas[76];
//--------------接收程式-----------------------------------
if(IdTCPClient1->Connected()){
while(!IdTCPClient1->IOHandler->InputBufferIsEmpty())
{
byte Date;
Date= IdTCPClient1->IOHandler->ReadByte();
if(Date!=0xFF){
Recive_Datas[i]=Date; //只接受76位
i++;
}
if((Recive_Datas[0]==0xAF)&&(Recive_Datas[1]==0xBF)&&//判斷是否接受到了DTU回傳資料頭和尾
(Recive_Datas[2]==0xCF)&&(Recive_Datas[3]==0xDF)&& //如果判斷資料為DTU回傳資料,則回傳給PC客戶端
(Recive_Datas[i-1]==0xFD)&&(Recive_Datas[i-2]==0xFC)&&
(Recive_Datas[i-3]==0xFB)&&(Recive_Datas[i-4]==0xFA)){
//------決議資料---------------------------------
AnsiString Meter_ID_H;//當前所讀表地址高位
AnsiString Meter_ID_L;//當前所讀表地址低位
AnsiString Meter_ID;
AnsiString Now_Heat;//當前熱量
AnsiString Now_Flow;//瞬時流量
AnsiString Cum_Flow;//累計流量
AnsiString In_Temp;//進水溫度
AnsiString Out_Temp;//出水溫度
AnsiString Cum_WorkingTime;//累計作業時間
AnsiString differentTemp;//溫度差
Meter_ID_H=AddZero(BCD_(Recive_Datas[19]))+AddZero(BCD_(Recive_Datas[18]))+AddZero(BCD_(Recive_Datas[17]));
Meter_ID_L=AddZero(BCD_(Recive_Datas[16]))+AddZero(BCD_(Recive_Datas[15]))+AddZero(BCD_(Recive_Datas[14]))+AddZero(BCD_(Recive_Datas[13]));
Meter_ID= Meter_ID_H+ Meter_ID_L;
Now_Heat=IntToStr((BCD_(Recive_Datas[32]))+(BCD_(Recive_Datas[33]))*100+(BCD_(Recive_Datas[34]))*10000)+'.'+(BCD_(Recive_Datas[31]));//當前熱量
Now_Flow=IntToStr((BCD_(Recive_Datas[44]))*100)+IntToStr((BCD_(Recive_Datas[43])))+'.'+IntToStr((BCD_(Recive_Datas[42]))+(BCD_(Recive_Datas[41])/100));//瞬時流量
Cum_Flow=IntToStr((BCD_(Recive_Datas[49]))*10000)+IntToStr((BCD_(Recive_Datas[48]))*100)+IntToStr((BCD_(Recive_Datas[47])))+'.'+IntToStr((BCD_(Recive_Datas[46])));//累計流量
In_Temp=IntToStr((BCD_(Recive_Datas[52]))*100+(BCD_(Recive_Datas[51])))+'.'+IntToStr(BCD_(Recive_Datas[50])); //進水溫度
Out_Temp=IntToStr((BCD_(Recive_Datas[55]))*100+(BCD_(Recive_Datas[54])))+'.'+IntToStr(BCD_(Recive_Datas[53])); //出水溫度
Cum_WorkingTime=IntToStr((BCD_(Recive_Datas[58]))*10000+(BCD_(Recive_Datas[57]))*100+BCD_(Recive_Datas[56])) ; //累計作業時間
float fdifferentT = StrToFloat(In_Temp)-StrToFloat(Out_Temp);
differentTemp= FormatFloat("0.00",fdifferentT); //進出口溫差
AnsiString year = IntToStr(BCD_(Recive_Datas[59])*100+ BCD_(Recive_Datas[60]));//年
AnsiString month = IntToStr(BCD_(Recive_Datas[61])); //月
AnsiString day = IntToStr(BCD_(Recive_Datas[62])); //日
AnsiString hour = IntToStr(BCD_(Recive_Datas[63])); //時
AnsiString minute = IntToStr(BCD_(Recive_Datas[64]));//分
AnsiString second = IntToStr(BCD_(Recive_Datas[65])); //秒
AnsiString Read_Time =year + "-" + month + "-" + day + " " + hour + ":" +minute + ":" + second;
AnsiString BatteryState;
if(Recive_Datas[66]==0x04){ //電池是否欠壓
BatteryState="欠壓";
}
else{
BatteryState="正常";
}
//---------決議完成------------------------------
AnsiString stry;
AnsiString strm;
AnsiString strd;
AnsiString strh;
AnsiString strmin;
AnsiString strs;
AnsiString strsystime;
SYSTEMTIME *GT=new SYSTEMTIME; // 系統時間變數
GetLocalTime(GT); //提取本地時間
stry = AnsiString(GT->wYear);
strm = AnsiString(GT->wMonth);
strd = AnsiString(GT->wDay);
strh = AnsiString(GT->wHour);
strmin = AnsiString(GT->wMinute);
strs = AnsiString(GT->wSecond);
strsystime = stry + "/" + strm + "/" + strd + " " + strh + ":" +strmin + ":" + strs; //system time in strsystime
AnsiString mysql;
TADOQuery *Query = new TADOQuery(this);
Query->Connection=fmMain->ADOConnection1;
Query->SQL->Clear();
Query->SQL->Add("select MeterNumber,LastRead from ylt.ResidentMeterRead where MeterNumber='"+Meter_ID+"'");
Query->Open();
float Heat=StrToFloat(Now_Heat)-StrToFloat(Query->FieldByName("LastRead")->AsString);
AnsiString HeatDiffence=FormatFloat("0.00",Heat);
if(CheckBox1->Checked==true){
mysql="UPDATE ylt.ResidentMeterRead SET CurrentRead = '"+Now_Heat+"',InstantaneousFlow ='";
mysql+=Now_Flow+"',CumulativeFlow ='"+Cum_Flow+"',InletTemperature ='"+In_Temp+"',EffluentTemperature='";
mysql+=Out_Temp+"',ReadMeterMark='成功',Heat='"+HeatDiffence+"',BatteryState='"+BatteryState+"',Runtime ='";
mysql+=Cum_WorkingTime+"',ReadingDate='"+strsystime+"'";
mysql+=" WHERE MeterNumber = '"+Meter_ID+"'";
}
else{
mysql="UPDATE ylt.ResidentMeterReadTemple SET CurrentRead = '"+Now_Heat+"',InstantaneousFlow ='";
mysql+=Now_Flow+"',CumulativeFlow ='"+Cum_Flow+"',InletTemperature ='"+In_Temp+"',EffluentTemperature='";
mysql+=Out_Temp+"',ReadMeterMark='成功',Heat='"+HeatDiffence+"',BatteryState='"+BatteryState+"',Runtime ='";
mysql+=Cum_WorkingTime+"',ReadingDate='"+strsystime+"'";
mysql+=" WHERE MeterNumber = '"+Meter_ID+"'";
}
Query->Close();
Query->SQL->Clear();
Query->SQL->Add(mysql); //將資料更新到資料庫中
Query->ExecSQL();
delete Query;
Query=NULL;
ReadSuccess=true;
for(int n=0;n<76;n++){
Recive_Datas[n]=0x0;
}
i=0;
}
}
}
//-------------SC決議程式結束--------------------------------
}
//---------------------------------------------------------------------------
void __fastcall TfmTimerReadOne::GPRSReadMeter(AnsiString MeterAddress,AnsiString TABLE)//GPRS讀表函式
{
if(IdTCPClient1->Connected()==false){
TADOQuery *pq= new TADOQuery(this);
pq->Connection=fmMain->ADOConnection1;
pq->SQL->Clear();
pq->SQL->Add("select IP,Port from ServerSet where TYPE='服務器'");
pq->Open();
IdTCPClient1->Host=pq->FieldByName("IP")->AsString;
IdTCPClient1->Port=StrToInt(pq->FieldByName("Port")->AsString);
IdTCPClient1->Connect();
}
unsigned short crc_value;//存放CRC檢驗結果
TADOQuery *pMeterReadCard = new TADOQuery(Application);
pMeterReadCard->Connection=fmMain->ADOConnection1;
pMeterReadCard->SQL->Clear();
pMeterReadCard->SQL->Add("select DTUNumber from ylt."+TABLE+" where MeterNumber = '"+MeterAddress+"'");
pMeterReadCard->Open();
AnsiString CardNo = pMeterReadCard->FieldByName("DTUNumber")->AsString;//與表號對應的采集器編號
pMeterReadCard->Close();
delete pMeterReadCard;
TADOQuery * pMeterReadChannel = new TADOQuery(Application);
pMeterReadChannel->Connection=fmMain->ADOConnection1;
pMeterReadChannel->SQL->Clear();
pMeterReadChannel->SQL->Add("select DTUChannel from ylt."+TABLE+" where MeterNumber = '"+MeterAddress+"'");
pMeterReadChannel->Open();
AnsiString ChannelNo = pMeterReadChannel->FieldByName("DTUChannel")->AsString;//與表號對應的通道號
pMeterReadChannel->Close();
delete pMeterReadChannel;
byte comm[39]; //發送資料陣列
comm[0] = 0x0A;
comm[1] = 0x0D;
comm[2] = 0x01;
comm[3] = 0x33;
comm[4] = 0xAF;
comm[5] = 0xBF;
comm[6] = 0xCF;
comm[7] = 0xDF;
comm[8] = 0x01;
comm[9] = StrToInt("0x"+CardNo.SubString(1,2));
comm[10]= StrToInt("0x"+CardNo.SubString(3,2));
comm[11]= 0x00;
comm[12]= 0x18;
comm[13]= 0xFE;
comm[14]= 0xFE;
comm[15]= 0x68;
comm[16]= 0x20;
comm[17]= StrToInt("0x"+MeterAddress.SubString(13,2));
comm[18]= StrToInt("0x"+MeterAddress.SubString(11,2));
comm[19]= StrToInt("0x"+MeterAddress.SubString(9,2));
comm[20]= StrToInt("0x"+MeterAddress.SubString(7,2));
comm[21]= StrToInt("0x"+MeterAddress.SubString(5,2));
comm[22]= StrToInt("0x"+MeterAddress.SubString(3,2));
comm[23]= StrToInt("0x"+MeterAddress.SubString(1,2));
comm[24]= 0x01;
comm[25]= 0x03;
comm[26]= 0x90;
comm[27]= 0x1F;
comm[28]= 0x01;
comm[29]= 0x00;
comm[30]= 0x16;
crc_value=https://bbs.csdn.net/topics/CRC16(comm+8,23); //進行CRC檢驗
comm[31]= crc_value%256;
comm[32]= crc_value/256;
comm[33]= 0xFA;
comm[34]= 0xFB;
comm[35]= 0xFC;
comm[36]= 0xFD;
comm[37]= 0x0B;
comm[38]= 0x0C;
i=0;
Timer2->Enabled=true;
for(int i=0;i<39;i++){
try{
IdTCPClient1->IOHandler->Write(comm[i]);
}
catch(...){
if(IdTCPClient1->Connected()==false){
TADOQuery *pq= new TADOQuery(this);
pq->Connection=fmMain->ADOConnection1;
pq->SQL->Clear();
pq->SQL->Add("select IP,Port from ServerSet where TYPE='服務器'");
pq->Open();
IdTCPClient1->Host=pq->FieldByName("IP")->AsString;
IdTCPClient1->Port=StrToInt(pq->FieldByName("Port")->AsString);
IdTCPClient1->Connect();
delete pq;
pq=NULL;
}
IdTCPClient1->IOHandler->Write(comm[i]);
}
}
DWORD Start = GetTickCount();
while(GetTickCount()-Start < 1000*5){ //等3秒
Application->ProcessMessages();//保證在延時期間程式可以相應oncomm事件
}
Timer2->Enabled=false;
IdTCPClient1->Disconnect();
}
uj5u.com熱心網友回復:
是服務端斷開了。uj5u.com熱心網友回復:
發送程式上面寫不下了,所以就副到這里了,很奇怪的是這個錯誤不是總出現,而是有時候出現,有時候不出現,還無法定位,所以只有求助各位大神了
void __fastcall TfmTimerReadOne::PrepareRead()
{
TfmLoading *fmLoading = new TfmLoading(Application);
fmLoading->Position=poScreenCenter;
fmLoading->Show();
fmLoading->Update();
if(IdTCPClient1->Connected()==false){
try{
TADOQuery *pq= new TADOQuery(this);
pq->Connection=fmMain->ADOConnection1;
pq->SQL->Clear();
pq->SQL->Add("select IP,Port from ServerSet where TYPE='服務器'");
pq->Open();
IdTCPClient1->Host=pq->FieldByName("IP")->AsString;
IdTCPClient1->Port=StrToInt(pq->FieldByName("Port")->AsString);
IdTCPClient1->Connect();
}
catch(...){
Application->MessageBoxW(L"連接服務器失敗,請檢查網路!",L"失敗",MB_OK);
BitBtn2->Enabled=true;
DBGrid1->Enabled=true;
delete fmLoading;
return;
}
}
if(ADOQuery1->RecordCount==0){
delete fmLoading;
Application->MessageBoxW(L"表中無記錄",L"訊息",MB_OK);
BitBtn2->Enabled=true;
return;
}
ADOQuery1->First();
int faultnumber=0;
int querynumber=0;
for(int i =0;i<ADOQuery1->RecordCount;i++){
int jishuqi=0;
ReadSuccess=false;
querynumber++;
Label1->Caption="抄表總數:"+IntToStr(querynumber);
while(ReadSuccess!=true){
GPRSReadMeter(ADOQuery1->FieldByName("表號")->AsString.Trim(),"ResidentMeterRead");
if(jishuqi==5){
jishuqi=0;
faultnumber++;
Label2->Caption="抄表失敗:"+IntToStr(faultnumber);
TADOQuery *Exception=new TADOQuery(this);
Exception->Connection=fmMain->ADOConnection1;
Exception->SQL->Clear();
if(CheckBox1->Checked==true){
Exception->SQL->Add("update ylt.ResidentMeterRead set ReadMeterMark ='失敗' where MeterNumber='"+ADOQuery1->FieldByName("表號")->AsString.Trim()+"'");
}
else {
Exception->SQL->Add("update ylt.ResidentMeterReadTemple set ReadMeterMark ='失敗' where MeterNumber='"+ADOQuery1->FieldByName("表號")->AsString.Trim()+"'");
}
Exception->ExecSQL();
delete Exception;
break;
}
jishuqi++;
}
ADOQuery1->Next();
}
DBGrid1->Enabled=true;
ADOQuery1->Close();
ADOQuery1->SQL->Clear();
AnsiString sql;
if(CheckBox1->Checked==true){
sql="select MeterNumber as 表號,DTUNumber as 集抄器號,DTUChannel 集抄器通道號,ResidentNumbe as 編碼";
sql+=",CommunityName as 小區名稱,BuildingName as 棟號,UnitName as 單元號,RoomName as 房間號,ResidentName as 用戶名稱,UserType as 用戶型別,Area as 面積,LastRead as 上次底數, ";
sql+="CurrentRead as 本次底數,ReadMeterMark 是否抄表,Succeed 是否成功,Heat as 用熱量,";
sql+="CumulativeFlow as 累計流量,InstantaneousPower as 瞬時功率,InstantaneousFlow as 瞬時流量,Runtime as 運行時間,";
sql+="FaultCondition as 故障狀態,InletTemperature as 進水溫度,EffluentTemperature as 回水溫度,BatteryState as 電池狀態,ReadingDate as 抄表日期";
sql+=" from ylt.ResidentMeterRead where FaultCondition<>'故障' ";
}
else {
sql="select MeterNumber as 表號,DTUNumber as 集抄器號,DTUChannel 集抄器通道號,ResidentNumbe as 編碼";
sql+=",CommunityName as 小區名稱,BuildingName as 棟號,UnitName as 單元號,RoomName as 房間號,ResidentName as 用戶名稱,UserType as 用戶型別,Area as 面積,LastRead as 上次底數, ";
sql+="CurrentRead as 本次底數,ReadMeterMark 是否抄表,Succeed 是否成功,Heat as 用熱量,";
sql+="CumulativeFlow as 累計流量,InstantaneousPower as 瞬時功率,InstantaneousFlow as 瞬時流量,Runtime as 運行時間,";
sql+="FaultCondition as 故障狀態,InletTemperature as 進水溫度,EffluentTemperature as 回水溫度,BatteryState as 電池狀態,ReadingDate as 抄表日期";
sql+=" from ylt.ResidentMeterReadTemple where FaultCondition<>'故障' ";
}
ADOQuery1->SQL->Add(sql);
ADOQuery1->Open();
delete fmLoading;
}
uj5u.com熱心網友回復:
可以重試,直到成功為止。應該沒什么影響。轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/93038.html
標籤:網絡及通訊開發
上一篇:BCB6 help
