大家邦我看看,有关客户端向服务器端发送数据流的问题!
打算写个小程序看看通讯服务器能连接多少个客户端得情况下还能正常通讯.
我想在客户端启动多个线程,让它们不停得给服务器端发送数据,服务器接收到数据以后,以文件得形式进行存储.当然,有时候可能数据传输得不完整,所以我在客户端发送得时候先对要发送得数据流进行MD5效验,产生32位效验码,先发送一个结构体(要发送得流得大小,里面包括生成得MD5效验码),服务器接收到流以后进行效验再生成一个MD5效验码,然后和开始接收到得结构体里得效验码进行比较,以此判断文件得完整性.
客户端每发送一次(int Sum++:客户端发送次数)
完整,服务器发送一个成功信息(int Suc++:客户端发送成功次数).失败,发送一个失败信息.(int Eor++ 失败次数).
程序如下:
客户端: Btn_SendFile():
{
IdTCPClient->Connect(); //Indy控件
Num = Edit1->Text.Trim().ToInt(); //欲启动线程数
for(int i = 0; i < Num; i++)
{
SendFile *ply = new SendFile(false);
ply->FreeOnTerminate = true;
ply->Resume();
}
}
客户端线程内容:
void __fastcall SendFile::Execute()
{
static int Sum = 0;
static int Eor = 0;
static int Suc = 0;
while(!Terminated)
{
if(!Form1->IdTCPClient->Connected())
Terminate();
else
{ //用到的结构体的申明都放在了线程的 .h 中
TMemoryStream *stream = new TMemoryStream();
HeadData HeadMsg; //结构体 (包括 char Size[10],char MD5[33])
HeadData HeadMsg1;
ResultData RetData; //结构体 接收服务器反馈信息(char Eor[6])
AnsiString size;
char *MD5s;
//待发送的数据
AnsiString SendStream ="dkfjdksjfkdsjfksdjfklsdjfdslkjflskdflkds";
size = IntToStr(SendStream.Length());
char *sy = size.c_str();
AnsiString RetEor = "succe"; //判断服务器反馈得信息
AnsiString RetSuc = "error";
stream->Write(SendStream.c_str(),SendStream.Length()); //读入流数据
AnsiString MD5Str = MD5_Data((char *)stream,SendStream.Length());//产生MD5码
MD5s = MD5Str.c_str(); //声明得字符指针指向MD5码
for(int i = 0; i < MD5Str.Length(); i++) //存储MD5码
{
HeadMsg.MD5[i] = MD5s[i];
}
HeadMsg.MD5[MD5Str.Length()]='\0';
for(int i = 0; i < size.Length(); i++) //数据流大小
{
HeadMsg.DataLen[i] = sy[i];
}
HeadMsg.DataLen[size.Length()] = '\0'; //发送文件头
Form1->IdTCPClient->WriteBuffer(&HeadMsg,sizeofHeadData));
Form1->IdTCPClient->WriteBuffer(stream,SendStream.Length(),true);
Form1->IdTCPClient->ReadBuffer(&RetData,sizeof(ResultData));
//读取返回信息
Sum++;
if(AnsiString(RetData.Cmd) == "succe")
Suc++;
if(AnsiString(RetData.Cmd) == "error")
Eor++;
}
}
/***************************************************************************************
服务器端:
static int FileNam; //全局变量,作为存储时的文件名
TCPServerExecute()
{
char Suc[6] = {'s','u','c','c','e','\0'};
char Eor[6] = {'e','r','r','o','r','\0'};
try{
TMemoryStream *stream=new TMemoryStream;
AThread->Connection->ReadBuffer(&HeadMsg1,sizeof(HeadData));//读取结构
int Size = StrToInt(AnsiString(HeadMsg2->Size)); //数据大小
AnsiString MD5Code = AnsiString(HeadMsg2->MD5); //MD5码
AThread->Connection->ReadBuffer(stream,sz); //接收数据
if(MD5_Data((char *)stream,sz).Trim() == MD5Code.Trim()) //校验并比对
{
for(int i = 0; i < 6; i++)
{
ReturnData.Cmd[i] = Suc[i]; //文件完整 succs
} //发送成功信息
AThread->Connection->WriteBuffer(&ReturnData,sizeof(ResultData));
stream->SaveToFile(FilePath+"\\ply\\"+AnsiString(FileNam)+".txt");//存储
}
else
{
for(int i = 0; i < 6; i++)
{
ReturnData.Cmd[i] = Eor[i]; //文件不完整 error
} //发送失败信息
AThread->Connection->WriteBuffer(&ReturnData,sizeof(ResultData));
}
}
__finally
{
stream->clear();
delete stream;
stream = NULL;
}
//======================================================================
问题1:
服务器端接收到流以后,将其存储为.TXT文件,但存储的全是乱码(传输中没有进行加密),在客
户端发送的时候及发送完以后(stream->SaveToFile("AAA.TXT")) 存储的内容都没问题.
问题2:
服务器执行完 stream->clear()后,报错.错误如下:
Project Server.exe raised exception class EAccessViolation with message 'Access
violation at address 01193C16 in module 'BORLNDMM.DLL'. Write of address 00000036'.
Process stopped. use Step or Run to continue.
问题3:
客户端启动多个线程发送数据,我想在发送一定数量的数据时将线程每个成功/失败的概率怎
么在窗体上表现出来?? (我感觉客户端中定义Sum,Eor,Suc没多大意义).
问题4:
程序中多于一个线程跑,总有错误出现,但我检查不出来.
唠哩唠叨了这么多 呵呵 谢谢了!!