求救关于线程阻塞模式下的TServerSocket控件的使用问题

stone_Ytou 2006-11-03 03:42:44
程序实现目标:
创建一个服务器,监听网络中的请求,如果收到请求,就发送数据给请求方

主要控件: TServerSocket
控件TServerSocket的属性ServerType为stThreadBlocking

主要代码如下:

线程类头文件:
class PACKAGE TMyServerThread : public Scktcomp::TServerClientThread
{
public:
// if true, FreeOnTerminate is set to false before the thread terminates,
// and the thread is left in the thread cache. When KeepInCache is false,
// the thread is freed when execution terminates.
__fastcall TMyServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket)
: Scktcomp::TServerClientThread(CreateSuspended, ASocket)
{ CreateSuspended = false; KeepInCache=true; FreeOnTerminate=false; };

// To implement this thread, you override the ClientExecute method instead of the
// Execute method.
void __fastcall ClientExecute(void);

private:
TWinSocketStream *pStream;
long downloadALLPre(bool isAll);
void downloadAll(bool isAll = true);
void uploadAll(bool isALl = true);
};
线程类的CPP文件
void __fastcall TMyServerThread::ClientExecute(void)
{
Synchronize(DownLoad);
}

void __fastcall TMyServerThread::DownLoad(void)
{
// make sure connection is active
while (!Terminated && ClientSocket->Connected)
{
try
{
// Now, use TWinSocketStream to read or write information
// over a blocking socket connection
int nResvLen = 0;
AnsiString temp = "";

pStream = new TWinSocketStream(ClientSocket, CLIENTWAITTIME);

try
{
//char pro_buf[PRO_PACKAGESIZE];
memset( pro_buf, 0, sizeof(pro_buf) );

// give the client 60 seconds to start writing
if (pStream->WaitForData(CLIENTWAITTIME))
{
nResvLen = pStream->Read(pro_buf,sizeof(pro_buf));
if (nResvLen == 0)
// (if can't read in 60 seconds) than close the connection
ClientSocket->Close();
else
{
// Client to Server test text
unassemblePackage(pro_buf, nResvLen);

if(strncmp(resvPack.header, sentPack.header, sizeof sentPack.header) == 0)
{
if(resvPack.order1 == sentPack.order1)
{
temp.sprintf("%8s", resvPack.machineid);
temp.SetLength(8);

if( 1 <= resvPack.order2 && resvPack.order2 <= 4)
{
DataModule1->curMachineID = temp;
sck_init(DataModule1->curMachineID.c_str());
Form1->Memo->Lines->Add("机器" + DataModule1->curMachineID + "加入连
接");
DataModule1->state = resvPack.order2;
}

switch(DataModule1->state)
{
case PRO_UPLOAD_PART:
uploadAll(false);
break;
case PRO_UPLOAD_ALL:
uploadAll();
break;
case PRO_DOWNLOAD_PART:
downloadAll(false);
break;
case PRO_DOWNLOAD_ALL:
downloadAll();
break;
}
}
else
{
Form1->Memo->Lines->Add("收到非正常信息帧,忽略");
nPackLen = assemblePackage(pro_buf, PRO_PACKAGESIZE, PRO_COMPELTE, NULL,0, NULL);
pStream->Write( pro_buf, sizeof(pro_buf));
DataModule1->init();
}
}
else
{
Form1->Memo->Lines->Add("收到非正常信息帧,忽略");
nPackLen = assemblePackage(pro_buf, PRO_PACKAGESIZE, PRO_COMPELTE, NULL,0, NULL);
pStream->Write( pro_buf, sizeof(pro_buf));
DataModule1->init();
}
}
}
else
ClientSocket->Close();
}
__finally
{
delete pStream;
}
}
catch (...)
{
HandleException();
}
}
}

TServerSocket采用stThreadBlocking模式,控件的OnGetThread事件代码如下:

void __fastcall TDataModule1::ServerSocketGetThread(TObject *Sender,
TServerClientWinSocket *ClientSocket,
TServerClientThread *&SocketThread)
{
SocketThread = new TMyServerThread(false, ClientSocket);
SocketThread->WaitFor();
SocketThread->Free();
}

问题:
当局域网中只有一台机器发来了下载请求时服务器程序运行正常,而当同时有两台机器下载的时候,服务器对其中的一台的请求在收到请求数据帧后却不给以相应的应答ACK数据帧,造成两台中有一台不能下载数据.

请大侠们全力指导,问题比较急
...全文
425 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
sbkopoky 2007-02-17
  • 打赏
  • 举报
回复
有一个香港和悦网络电话的源文件 ,有兴趣妨进入我的BLOG看看
stone_Ytou 2006-11-10
  • 打赏
  • 举报
回复
只有1号机下载的显示情况:
机器11111111加入连接
机器11111111pStream=16147272
机器11111111ClientSocket=16242516
监听到下载请求
验证通过
开始覆盖下位机数据流程:
创建零时文件...
开始生成数据... ..100 %
成功生成零时文件!
文件大小: 9504 字节
被分为 10 包,每个 960 字节
向下位机发送数据包数
收到下位机确认,开始发送数据
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 d137cbb6528082, 8f72cbf63c
发送数据报文2 3abbe3b93360c3, eb3ae1f08f
pro_buf:30303030303030
发送数据 No. 1 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 480c813c841437, b35f725d40
发送数据报文2 a380a933e5f476, d7d489a455
pro_buf:30303030303030
发送数据 No. 2 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 0c0010182d4fd8, c4a9f571c1
发送数据报文2 e78c38174caf99, a0c19be1d7
pro_buf:30303030303030
发送数据 No. 3 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 ee40e4958dbc1f, e2bea0c0b6
发送数据报文2 05cccc9aec5c5e, 863ac384db
pro_buf:30303030303030
发送数据 No. 4 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 5a17e1fed12902, 713d717e92
发送数据报文2 b19bc9f1b0c943, 15256862d5
pro_buf:30303030303030
发送数据 No. 5 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 d231716f26bae4, 09c2f8cb49
发送数据报文2 39bd5960475aa5, 6d00997899
pro_buf:30303030303030
发送数据 No. 6 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 6434c44abd5ffe, 945792e993
发送数据报文2 8fb8ec45dcbfbf, f0a0c0e431
pro_buf:30303030303030
发送数据 No. 7 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 da07323977f240, 744a25d2e8
发送数据报文2 318b1a36161201, 10be342c6f
pro_buf:30303030303030
发送数据 No. 8 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 37ef5053fb59fd, d69ca35d12
发送数据报文2 dc63785c9ab9bc, b2fcfde740
pro_buf:30303030303030
发送数据 No. 9 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 1e181c7444dc08, 32a10169f4
发送数据报文2 f594347b253c49, 5664e84d91
pro_buf:30303030303030
发送数据 No. 10 / 10
数据发送完成
下位机确认完成
完全覆盖数据传输成功完成,关闭连接
stone_Ytou 2006-11-10
  • 打赏
  • 举报
回复
以下是我在调试时两台机器下载的时候在Memo中显示的信息:

1号和2号机同时进行的显示情况:
机器22222222加入连接
机器22222222pStream=16108512
机器22222222ClientSocket=16214060
监听到下载请求
验证通过
开始覆盖下位机数据流程:
创建零时文件...
开始生成数据... ..10 %
机器11111111加入连接
开始生成数据... ..15 %机器11111111pStream=16237860
开始生成数据... ..20 %机器开始生成数据... ..25 %
开始生成数据... ..45 %
开始生成数据... ..100 %
成功生成零时文件!
文件大小: 733 字节
被分为 1 包,每个 960 字节
向下位机发送数据包数
开始覆盖下位机数据流程:
创建零时文件...
开始生成数据... ..100 %
成功生成零时文件!
文件大小: 9504 字节
被分为 10 包,每个 960 字节
向下位机发送数据包数
收到下位机确认,开始发送数据
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 4f35bb066bb0d3, 80f53f48ff
发送数据报文2 a4b993090a5092, e4aa75fa20
pro_buf:30303030303030
发送数据 No. 1 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 2b09ddb7876e0d, 835247cac3
发送数据报文2 c085f5b8e68e4c, e7eb90e493
pro_buf:30303030303030
发送数据 No. 2 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 dfe2b4f6151154, 524af1544e
发送数据报文2 346e9cf974f115, 36af0e9019
pro_buf:30303030303030
发送数据 No. 3 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 581d34aa4bb970, 3d4f7103d6
发送数据报文2 b3911ca52a5931, 598eeb10ee
pro_buf:30303030303030
发送数据 No. 4 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 86e3fe84e9c2f7, b598b21a35
发送数据报文2 6d6fd68b8822b6, d19c2851a3
pro_buf:30303030303030
发送数据 No. 5 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 9f0fe7d185c511, 330c4d6f61
发送数据报文2 7483cfdee42550, 57c68ad7b8
pro_buf:30303030303030
发送数据 No. 6 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 5cae0c5b1be9de, dac97a3a1b
发送数据报文2 b72224547a099f, bef17e9aee
pro_buf:30303030303030
发送数据 No. 7 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 5cc072c64ab8c9, c48fb29a5e
发送数据报文2 b74c5ac92b5888, a0b722e6bd
pro_buf:30303030303030
发送数据 No. 8 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 87055f92682bed, 4bab452671
发送数据报文2 6c89779d09cbac, 2f4508a7f2
pro_buf:30303030303030
发送数据 No. 9 / 10
下位机确认收到数据
file_buf=30303030303030303030
发送数据报文1 928f76cc855343, 9b9f9bd55b
发送数据报文2 79035ec3e4b302, ff1b347704
pro_buf:30303030303030
发送数据 No. 10 / 10
数据发送完成
下位机确认完成
完全覆盖数据传输成功完成,关闭连接
stone_Ytou 2006-11-10
  • 打赏
  • 举报
回复
我发现两台机器请求下载时,后请求的会干扰先请求的,这是为什么呢?
do2008 2006-11-06
  • 打赏
  • 举报
回复
还是不能做出响应呀,这个就比较难判断是什么原因了.

最好在IDE中集成调试一下,单步跟踪出你的DownLoad();函数中,看看到底卡在什么地方吧
stone_Ytou 2006-11-06
  • 打赏
  • 举报
回复
这样处理了还是有问题,第二台机器同时访问的时候服务器还是不能正常给出响应
do2008 2006-11-03
  • 打赏
  • 举报
回复
发急了,楼上这一贴的ClientExecute改为如下;

void __fastcall TMyServerThread::ClientExecute(void)
{
//Synchronize(DownLoad); 这一句不能要了

try
{
DownLoad();
}
catch(exception &e)
{
fun_ShowLog(e.message);//添加一个异常处理,显示异常的信息到memo中,
}

//当然,LZ不很必要就直接一句DownLoad();就OK了
}

代码我没有调试过,LZ自行调试。
do2008 2006-11-03
  • 打赏
  • 举报
回复
楼主的ClientExecute函数,就只有一句Synchronize(DownLoad);呵呵,这是非常不推荐的做法,
Lz要再体会一下Synchronize这个函数的作用及影响;

class PACKAGE TMyServerThread : public Scktcomp::TServerClientThread
{
public:
// if true, FreeOnTerminate is set to false before the thread terminates,
// and the thread is left in the thread cache. When KeepInCache is false,
// the thread is freed when execution terminates.
__fastcall TMyServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket)
: Scktcomp::TServerClientThread(CreateSuspended, ASocket)
{ CreateSuspended = false; KeepInCache=true; FreeOnTerminate=false; };

// To implement this thread, you override the ClientExecute method instead of the
// Execute method.
void __fastcall ClientExecute(void);

//添加两个函数
void fun_SetLog();
void fun_ShowLog(String ls);

private:
TWinSocketStream *pStream;
long downloadALLPre(bool isAll);
void downloadAll(bool isAll = true);
void uploadAll(bool isALl = true);

String fLog;//日志
};
线程类的CPP文件
void __fastcall TMyServerThread::ClientExecute(void)
{
Synchronize(DownLoad);
}

void __fastcall TMyServerThread::DownLoad(void)
{
// make sure connection is active
while (!Terminated && ClientSocket->Connected)
{
try
{
// Now, use TWinSocketStream to read or write information
// over a blocking socket connection
int nResvLen = 0;
AnsiString temp = "";

pStream = new TWinSocketStream(ClientSocket, CLIENTWAITTIME);

try
{
//char pro_buf[PRO_PACKAGESIZE];
memset( pro_buf, 0, sizeof(pro_buf) );

// give the client 60 seconds to start writing
if (pStream->WaitForData(CLIENTWAITTIME))
{
nResvLen = pStream->Read(pro_buf,sizeof(pro_buf));
if (nResvLen == 0)
// (if can't read in 60 seconds) than close the connection
ClientSocket->Close();
else
{
// Client to Server test text
unassemblePackage(pro_buf, nResvLen);

if(strncmp(resvPack.header, sentPack.header, sizeof sentPack.header) == 0)
{
if(resvPack.order1 == sentPack.order1)
{
temp.sprintf("%8s", resvPack.machineid);
temp.SetLength(8);

if( 1 <= resvPack.order2 && resvPack.order2 <= 4)
{
DataModule1->curMachineID = temp;
sck_init(DataModule1->curMachineID.c_str());

//Form1->Memo->Lines->Add("机器" + DataModule1->curMachineID + "加入连接");
fun_ShowLog("机器" + DataModule1->curMachineID + "加入连接");

DataModule1->state = resvPack.order2;
}

switch(DataModule1->state)
{
case PRO_UPLOAD_PART:
uploadAll(false);
break;
case PRO_UPLOAD_ALL:
uploadAll();
break;
case PRO_DOWNLOAD_PART:
downloadAll(false);
break;
case PRO_DOWNLOAD_ALL:
downloadAll();
break;
}
}
else
{
//Form1->Memo->Lines->Add("收到非正常信息帧,忽略");
fun_ShowLog("收到非正常信息帧,忽略");
nPackLen = assemblePackage(pro_buf, PRO_PACKAGESIZE, PRO_COMPELTE, NULL,0, NULL);
pStream->Write( pro_buf, sizeof(pro_buf));
DataModule1->init();
}
}
else
{
//Form1->Memo->Lines->Add("收到非正常信息帧,忽略");
fun_ShowLog("收到非正常信息帧,忽略");
nPackLen = assemblePackage(pro_buf, PRO_PACKAGESIZE, PRO_COMPELTE, NULL,0, NULL);
pStream->Write( pro_buf, sizeof(pro_buf));
DataModule1->init();
}
}
}
else
ClientSocket->Close();
}
__finally
{
delete pStream;
}
}
catch (...)
{
HandleException();
}
}
}


void TMyServerThread::fun_SetLog()
{
Form1->Memo->Lines->Add(fLog); //显示日志
}

void TMyServerThread::fun_ShowLog(String ls)
{
fLog = ls;
Synchronize(fun_SetLog);//由主线程执行fun_SetLog函数
}
do2008 2006-11-03
  • 打赏
  • 举报
回复
问题出在你的ClientExecute函数:
>>void __fastcall TMyServerThread::ClientExecute(void)
{
Synchronize(DownLoad);
}

TServerSocket在stThreadBlocking模式下,为每一个TCP连接创建一个来服务,这LZ也应该知道;
但要注意,Synchronize(DownLoad)这个函数,会使DownLoad这个函数的是由主线程来执行的;

应该改成这样

void __fastcall TMyServerThread::ClientExecute(void)
{
DownLoad;//这样就是由TMyServerThread线程来执行;
}


看样子,LZ是打算在DownLoad中,用Form1->Memo->Lines->Add这种方式来显示日志;
可以采用别的方法,来做,见下一贴

1,317

社区成员

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

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