delphi socket使用心得

<strong><span style="font-size:18px;color:#ff0000;">下面的代码中包含了一个消息接收器,当消息接收器收到消息后,将socket,收到的消息,状态,封装成对象,保存到tstringlist中,stringlist.strings[0]里面保存了对象的ID(也就是命令的序号,从1..X);然后放一个定时器,定时器1S中去查看命令列表;把第一条命令的stringlist.strings[0]设置为‘0’,如果定时器检查到第一条的这个标志是0,则退出,不处理。证明系统正在处理其中的一条命令。把这个命令发送给子的socketserver; 在clientread里读取数据,然后处理,处理完后,返回信息回去,证明这个命令处理完了,把处理的状态返回给消息发送器。然后调用命令对象里的socket发送给命令发送者,去掉第一条命令。   然后定时器检测到命令存在时,发送命令,设置状态。知道处理完所有的命令。</span></strong>
 
<pre name="code" class="delphi">procedure write_log(str: string);
var
  F: TextFile;
  mfile: string;
begin
  try
    //判断保存日志文件的目录是否存在
    if not DirectoryExists(ExtractFilePath(ParamStr(0)) + 'log') then
      MkDir(ExtractFilePath(ParamStr(0)) + 'log');

    //按日期及时间设定保存日志的文件名
    mfile := ExtractFilePath(ParamStr(0)) + 'log\' + formatdatetime('yyyy-mm-dd',Now) + '.txt';

    AssignFile(F,mfile);
    if not FileExists(mfile) then
      Rewrite(F);//如果文件不存在,则创建一个新的文件,并写入
    Append(F); //追加写入
    Writeln(F,str);//写入并换行
    CloseFile(F);
  except
  end;
end;


 
procedure TfmDKGZT.DJsocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  sReceive,sDJBH: string;
  slReceive: TStringList;
begin
  // 如果需要做批发,uni_basedatabill里的Execute;重新打开单据上的监听端口;
  // 因为每张单据需要一个监听端口,再打开别的单据之前,请关掉别的端口;
  // 这个时候需要在每个命令中保存要打开的单据号。
  slReceive := TStringList.Create;
  sReceive := socket.ReceiveText;
  slReceive.CommaText := sReceive;
  sDJBH := slReceive[0];
  if FMainTbl.Locate('DJBH',SDJBH) then
  begin
    if isWJSnoprint and (GetNameFromCode('DKGZT','DJBH','YS',SDJBH)<>'1')  then
    begin
      socket.SendText('1');
      Exit;
    end;
    DiyPrint;
    write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '单据打印成功】'+'单据编号:'+SDJBH);
    write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '】'+'------------------------------------');
    socket.SendText('0');
  end
  else
  begin
    socket.SendText('2');
  end;
end;
  // 创建窗体的时候,打开socket;
  configIni := tinifile.Create(ExtractFilePath(Paramstr(0))+'SysBusiness.ini');
  DK := configIni.ReadInteger('PORTS','DKGTX_N',3005);
  configini.Free;
  DJsocket.Port := DK;
  try
    DJsocket.Open;
    write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '监听服务已打开】'+'端口号:'+inttostr(DJsocket.port));
  except
    on E:Exception do
    begin
      if pos('10048',E.Message)>0 then
         Uni_Function.ShowApplicationMsg('端口:'+inttostr(DK)+'被占用,将无法通过IPAD调用打印服务!',IERRORMSG);
    end;
  end;

  TDKGZTXX = class
    Fsocket: TCustomWinSocket;
    FTxt:String;
    Fstate: integer;
  public
    constructor create();

  end;

procedure Tfrm_MainForm.mainSerSocketClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  acceptList: TStringList;
  acceptStr: String;
  modid,strimodid: string;
  imodid,DK,POS_i: integer;
  configIni: tinifile;
  dkgztxx: TDKGZTXX;
begin
  //这里不一定是一次接收,一个命令,有可能一次接收了多个命令。
  acceptStr:= socket.ReceiveText;
 // write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '收到加密消息】'+socket.RemoteAddress+':'+inttostr(socket.RemotePort)+':'+inttostr(socket.socketHandle)+':'+acceptStr);
  acceptstr := Uni_Dlls.Encryption(acceptstr,false);
  write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '收到打印请求】'+socket.RemoteAddress+':'+inttostr(socket.RemotePort)+':'+acceptStr);
  POS_i :=posEX('81006006',acceptstr,9);
  if pos_i >0 then
  begin
    while pos_i>0 do
    begin
      inc(taskcount);
      dkgztxx := Tdkgztxx.Create;
      dkgztxx.Fsocket := socket;
      dkgztxx.FTxt := leftstr(acceptstr,pos_i-1);
      acceptstr := midstr(acceptstr,pos_i,10000);
      POS_i :=posEX('81006006',9);
      tasklist.Addobject(inttostr(taskcount),dkgztxx);
      write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '加到任务列表】'+socket.RemoteAddress+':'+inttostr(socket.RemotePort)+'*'+inttostr(taskcount)+'*'+dkgztxx.FTxt);
    end;
  end;
  inc(taskcount);
  dkgztxx := Tdkgztxx.Create;
  dkgztxx.Fsocket := socket;
  dkgztxx.FTxt := acceptstr;
  tasklist.Addobject(inttostr(taskcount),dkgztxx);
  write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '加到任务列表】'+socket.RemoteAddress+':'+inttostr(socket.RemotePort)+'*'+inttostr(taskcount)+'*'+dkgztxx.FTxt);
  time_socket.Enabled := true;
end;

constructor TDKGZTXX.create;
begin
  Fstate :=0;
end;

procedure Tfrm_MainForm.time_socketTimer(Sender: TObject);
var
  acceptList: TStringList;
  acceptStr: String;
  modid,i: integer;
  configIni: tinifile;
  dkgztxx: TDKGZTXX;
  sendmessage: string;
begin
  // 如果任务队列中没数据,则退出。
  if tasklist.Count = 0 then
  begin
    time_socket.Enabled := false;
    exit;
  end;
  // 如果第一条数据的索引字符串是'0’,表示第一条记录还没打印,继续等待打印
  // 结束,不进行处理。
   if tasklist.Strings[0] = '0' then exit;
    acceptList := TStringList.Create;
    dkgztxx := Tdkgztxx(tasklist.Objects[0]);
    acceptList.CommaText := dkgztxx.FTxt ;
    modid := acceptlist[0];
    acceptlist.Delete(0);
    sendmessage := acceptlist.CommaText;
    acceptlist.Free;
    // 分离出第一个命令,打开窗体;
    if not isWindowExists(modid,True) then
    begin
      if length(modid)<3 then exit;
        striModid:=copy(modid,2,2);
        iModId:=StrToInt(striModid);
        Uni_RunForms.ActivateMdiChildForm(iModId,modid,OUser.Power.GetFuncAlias(modid),'',_bsbrowse);
        write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '单据打开】'+dkgztxx.Fsocket.Remoteaddress+':'+inttostr(dkgztxx.Fsocket.RemotePort)+':'+modid);
      // 创建窗体的时候,打开socket;
        configIni := tinifile.Create(ExtractFilePath(Paramstr(0))+'SysBusiness.ini');
        DK := configIni.ReadInteger('PORTS',3005);
        configini.Free;
        mainCSocket.Port := DK;
        mainCSocket.Open;
    end;
    //刚开启端口的时候,active不一定打开
    if maincsocket.Active then
    begin
      maincsocket.socket.SendText(sendmessage);
      write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '内部信息发送】'+dkgztxx.Fsocket.Remoteaddress+':'+inttostr(dkgztxx.Fsocket.RemotePort)+':'+sendmessage);
      tasklist.Strings[0] :='0';
    end;
end;

procedure Tfrm_MainForm.FormDestroy(Sender: TObject);
begin
  tasklist.Free;
end;

procedure Tfrm_MainForm.mainCSocketRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  dkgztxx: TDKGZTXX;
  jo,jt:ISuperObject;
  printstr,strN: string;
begin
   dkgztxx := Tdkgztxx(tasklist.Objects[0]);
   try
//   status 是否成功标志  0 失败  >0 成功   message 成功消息/ 活着失败原因  data: 就返回那个单据编号吧
     jt  := SO();
     jt.S['status'] := '0';
     jt.s['data'] := midstr(dkgztxx.FTxt,10,1000);
     strN := socket.ReceiveText;
     if strN = '0' then
     begin
       jt.S['message'] :='打印成功!';
     end else if  strN = '1' then
     begin
       jt.S['status'] := '1';
       jt.S['message'] :='未结算不可打印!';
     end else
     begin
       jt.S['message'] :='未找到单据';
       jt.S['status'] := '1';
     end;
     printstr := jt.s['data']+jt.S['message'];
     dkgztxx.FSocket.SendText(jt.Asstring);
     write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '对外发送消息】'+jt.Asstring);
   except
     on E: Exception do
      showmessage(E.Message);
   end;
   dkgztxx.Free;
   tasklist.Delete(0);
  // write_log('【' + FormatDateTime('yyyy-mm-dd hh:nn:ss ',Now) + '内部信息接收】'+strN);
end;

procedure Tfrm_MainForm.mainSerSocketClientError(Sender: TObject;
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
  var ErrorCode: Integer);
begin
  errorcode :=0;
end;

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...