请高手帮忙TclientSocket问题,分不够再加啊:在ctBloching,用三个线程发送队列中的数据时,为么务服端会出现乱码?谢谢 (200分)

H

hcai

Unregistered / Unconfirmed
GUEST, unregistred user!
程序(线程1)
unit myThread1;

interface

uses
Classes,sysutils,winsock,dialogs,ScktComp;

type
BIQThread1 = class(TThread)
private
{ Private declarations }
public
SckStream : TwinSocketStream;
// sendBuf : array[0..299] of widestring;
// recBuf : array[0..299] of widestring;
sendBuf : ^Widestring;
recBuf : ^widestring;

protected

procedure Execute; override;
end;
implementation
uses
SendMsg;
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure BIQThread3.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ BIQThread1 }

procedure BIQThread1.Execute;
var
fun_type: string;
fun_bankID : STRING;
fun_date : string;
fun_time : string;
P: INTEGER;
SendSucc: integer;
outTimeSQL,runSQL : string;
recTime : integer;

BANKID : string; //包中的交易流水号
BagType,ResultName : string; //包中的交易类型
BagResult : string; //包中的交易结果

dzDate : string; //对帐日期
dzTime : string; //对帐时间

Buf_Length : integer;

begin
SckStream := TwinSocketStream.Create(BIQ2002SCK.clientSCK.Socket,TimeOut);
new(sendBuf);
recTime :=0;
with BIQ2002SCK do
begin //
sendBuf := myPush.Pop; //从队列中取出数据
Buf_Length := Length(sendBuf^) +1;

fun_type:=copy(send_bag^,4,2); //取出各交易标记
fun_bankID := copy(send_bag^,6,16);
fun_date := copy(send_bag^,22,8);
fun_Time := copy(send_bag^,30,6);

for p:=0 to repeatTimes do
begin
// Wstream.Write(PWideChar(buffer),isend);
SendSucc:=SckStream.Write(PWideChar(sendbuf)^, buf_Length); //发送数据。以下可以不管了,服务端收到的是乱码,请各位帮忙阿。
if SendSucc>0 then
begin
Sendok1:=false;
if (fun_type='KF')OR(fun_type='FK')OR(fun_type='CZ')then
runSQL := 'Update T_NEW_FEE_RECORD SET Deal_Flag=2 where Deal_Flag=1 and SERIALNO='''
+fun_bankID+'''';
if fun_type='ZZ' then
runSQL := 'UPdate T_JCHECK SET BCHECK_FLAG=4 WHERE SERIALNO='''
+fun_bankID+'''';
if fun_type='DZ' then
runSQL := 'UPDATE T_NEW_FEE_RECORD SET DCHECK_FLAG=5 WHERE SERIALNO='''
+fun_bankID+'''';

BIQ2002SCK.ADOcomm.CommandText:=runSQL;

try
if ADOconn.InTransaction then BIQ2002SCK.ADOconn.CommitTrans;
ADOconn.BeginTrans;
ADOcomm.Execute;
ADOconn.CommitTrans;
except
BIQ2002SCK.ADOconn.RollbackTrans;
end; //END: EXCEPT
break; //发送成功退出循环
end; //end: if....
end; //end : for...

if fun_type='KF' then //insert : grid...
BagType:= '收费';
if fun_type='FK' then
BagType:= '退费';
if fun_type='CZ' then
BagType:='冲正';
if fun_type='ZZ'then
BagType:='对总帐';
if fun_type='DZ'then
BagType:='对明细';


jelsID:=fun_bankid; //交易流水号
JEDATE:=copy(fun_date,1,4)+'-'+copy(fun_date,5,2)+'-'+copy(fun_date,7,8); //交易日期
JETIME:=copy(fun_time,1,2)+':'+copy(fun_time,3,2)+':'+copy(fun_time,5,2); //交易时间

send_State:='1';
insert_grid_bag(''); //插入表格;
send_State:='0';

//接收过程

while (not Terminated) and (clientSCK2.Active) do
begin

new(recBuf);
{ give the client 60 seconds to start writing }
if SCKStream.WaitForData(100) then
if SCKStream.Read(recBuf, sizeof(recBuf)) = 0 then
begin
recTime:=recTime+100;
if recTime>=TimeOut then break; //进入超时控制
end
else
begin
inPush.Push(recBuf); //压入队列
ClientSCK.Close;
SCKstream.Free;
end; //

end;

BANKID := Get_Flag(recbuf^,6,16,'head','KF'); //银行流水号
BagType:= Get_Flag(recbuf^,4,2,'head','KF'); //交易类型
BagResult := Get_Flag(recbuf^,40,2,'head','KF'); //交易结果
DzDate := Get_Flag(recbuf^,22,8,'head','KF'); //交易日期
DzTime := Get_Flag(recbuf^,30,6,'head','KF'); //交易时间

if bagResult<>'00'then
begin
AdoGetType.Close;
AdoGetType.SQL.Clear;
AdoGetType.SQL.Add('select NAME from T_FEE_RETCODE where FEE_RETCODE='''+Trim(bagType)+'''');
AdoGetType.Open;
if AdoGetType.IsEmpty=false then
ResultName := AdoGetType.fieldbyname('NAME').asstring
else
ResultName := '不确定';
AdoGetType.Close;
end;

DzDate:=copy(dzDate,1,4)+'-'+copy(dzDate,5,2)+'-'+copy(dzDate,7,2); //对总帐日期

if ((BagType='KF')or(BagType='FK')or(BagType='CZ'))and(bagResult='00') then //处理退费、收费交易
ResultName:= '成功';
if ((BagType='ZZ')OR(BagType='DZ'))AND(BagResult='00')then
ResultName:= '平帐';

rec_result :=ResultName;
Rec_status := '成功';
if BagType='KF' then
BagType:= '收费';
if BagType='FK' then
BagType:= '退费';
if BagType='CZ' then
BagType:='冲正';
if BagType='ZZ'then
BagType:='对总帐';
if BagType='DZ'then
BagType:='对明细';

rec_Type := bagType;
rec_bankID := bankID;
rec_Date := DzDate;
rec_time := copy(DzTime,1,2)+':'+copy(DzTime,3,2)+':'+copy(DzTime,5,2);
new(rec_bag);
rec_bag^:=recbuf^;
rec_state:='1';

rec_state:='0';
BagType:='';

if recTime>=TimeOut then //进入超时控制
begin
SCKstream.Free;
BIQ2002SCK.clientSCK.Close;
if (fun_type='KF')OR(fun_type='FK')OR(fun_type='CZ')then
OutTimeSQL:='UPDATE T_NEW_FEE_RECORD SET DEAL_FLAG=3 WHERE SERIALNO='''
+fun_bankID+'''';
if (fun_type='ZZ') THEN
outTimeSQL:='UPDATE T_JCHECK SET BCHECK_FLAG=3 WHERE SERIALNO='''
+fun_bankid+'''';
if (fun_Type='DZ') THEN
outTimeSQL:='UPDATE T_JCHECK SET BCHECK_FLAG=3 WHERE SERIALNO='''
+fun_bankid+'''';

BIQ2002SCK.ADOcomm.CommandText:=OutTimeSQL;
try
if BIQ2002SCK.ADOconn.InTransaction then BIQ2002SCK.ADOconn.CommitTrans;
BIQ2002SCK.ADOconn.BeginTrans;
BIQ2002SCK.ADOcomm.Execute;
BIQ2002SCK.ADOconn.CommitTrans;
except
BIQ2002SCK.ADOconn.RollbackTrans;
end;

BIQ2002SCK.OutTime_lab.Text:= inttostr(strtoint(BIQ2002SCK.OutTime_lab.Text)+1);
SendStatus:='超时';

Insert_Grid_bag(''); //插入grid

end;//end:while.....
bagType:='';
fun_type:='';
end; //end : with
end; //end : begin
end.
 
如果你线程中
SckStream := TwinSocketStream.Create(BIQ2002SCK.clientSCK.Socket,TimeOut);
的BIQ2002SCK.clientSCK.Socket参数在三个线程都是同一个的话,那你接收
部分的代码就要重写了
 
你一个线程一个连接,而且速度要调整,不要太快了[:D]
 
to mywyn:
三个线程各建立一个WINSOCKETSTREAM,调试是只用一个线程,还不行。
 
一个线程一个连接,由于你只有一个接受线程,而发送线程有3个,
多线程的切换由系统控制,所以产生了烂码
 
这种情况一般是你收到的数据不全,或数据次序颠倒(多线程)造成的。
我看了一下你的程序,说实话看不大明白。不过有一点,你好像每次都忽略
接收到的字节数。有可能你想接收的字节数小于你实际收到的。也就是说你
执行了 if SCKStream.Read(recBuf, sizeof(recBuf)) = 0 then后,返回值
虽然不等于0但收到的数据小于sizeof(recBuf)),recBuf的一部分数据就是随机
的了。但是程序仍然为跳到else处执行。
 
同意mywyn,不过我不知道你的接受线程是如何写的
 
to mywyn:
在服务端接收到的信息已是乱码的了!
 
所有的widestring和pwidechar,全换成string。数据中有中文的暂时换成E文
 
用buf:array[1...MAXLEN]of char;来保存数据
 
两位兄弟:
汉字显示出来都是乱码阿,为什么异步不会阿。
 
你直接用string类型,
 
你发个收和发的简易版吧!这样猜来猜去也不是办法。
 
接受部分
procedure TForm1.ClientSocket2Read(Sender: TObject;
Socket: TCustomWinSocket);
var len:integer;
temp:string;
begin
if stStatue=stgetFile then
begin
Len:=Socket.ReceiveLength;
Temp:=Socket.ReceiveText;
filem.Write(PChar(Temp)^,len); //filem是一个文件流
inc(allLen,len);
if allLen=getfilesize then //allLen是文件长度,你先传送过来
ShowMessage('文件接受完毕!');
end;

发送部分
const
MAX_LEN=2048;

var
iSen:integer; //iSen发送出去的长度
iSize:integer; //文件长度 最好是全局变量
buf:array[1..MAXLEN]of char;
senlen:integer; //每次应该发送的长度
ret:integer; //实际发送的文件长度
filen:TFileStream; //最好是全局变量

iSen:=0;
while iSen<iSize do
begin
FillChar(buf,MAX_LEN,0);
if iSize-iSen>MAX_LEN then senlen:=MAX_LEN
else senLen:=iSize-iSen;
filen.Position:=iSen;
filen.Read(buf,senLen);
ret:=ClientSocket1.Socket.SendBuf(buf,senLen);
inc(iSen,ret);
end;
 
多谢两位的帮忙,我的问题已经解决啦,即在发送之前把:WIDESTRING转成STRING就可以啦,谢谢
 
顶部