ClientSocket のイベントについて

解決


固まる  2004-05-27 02:51:04  No: 9146

いつもお世話になっております。

VBのWinsock1コントロールには、送信処理が完了したときに発生する
SendComplete というイベントがあるのですが、
DelphiのInternetタブのTClientSocketコンポーネントには、
このイベントがないみたいです。

他のコンポーネントで送信処理が完了したときに発生するようなイベントがあるものはありますでしょうか。

また、DelphiでWinSockを使用するには、どのようにすればいいでしょうか。


固まる  2004-05-27 03:44:50  No: 9147

やりたいことはと言えば、データを送信する際に、
送信が完了するまで、空ループを行いたいのですが、
TClientSocket で実現する方法がわからないのです。


ふじっこ  2004-05-27 20:54:22  No: 9148

参考になれば良いのですが・・
TClientSocketを使ってSendComplateイベントもどきを実装するには
送信先相手サーバへ何バイト送信する予定で実際何バイト無事送信できたか?
を比較するようにすれば、可能です。
TclientSocketのSendbufを使うと送信するバッファと送信サイズが
ほぼ固定化するのでその比較は楽です
TClientSocketのBytesSendプロパティをなぜ使わないのかというと
知らずにSendBufメソッドを使って送信バイトと送信できたバイト数を
比較していたからです(汗


固まる  2004-05-28 00:01:27  No: 9149

すいません、よろしければサンプルプログラムを教えていただけないでしょうか。
また、SendBuf(var Buf; Count: Integer): Integer; メソッドの
引数 Buf は、どんな型の変数になりますか、(バイト配列なんかでもOKでしょうか)


ふじっこ  2004-05-28 00:51:41  No: 9150

すでに画面にTCPClientが張り付いてるとして
ボタンクリック時に送信し、サイズチェックし、
すべて送信完了できたら、他を行なう場合
下記のようになると思います。
送信バッファや、送信内容は適当です。
ファイルの内容をサーバーに送信し完了を待つのであれば
ファイルサイズからもとに、SendBufで送信できたサイズを
比較していくと良いと思います。
procedure TForm1.Button1Click(Sender: TObject);
var
  Buf :Array [0..10]of char;
  buflen:Integer;
  nRet:Integer;
  nTotalsize:Integer;
  nNowSendSize:Integer;
begin
  buflen:=3;
  Buf[0] :='A';
  buf[1] :='B';
  buf[2] :='C';
  nTotalsize := 3;
  nNowSendSize :=0;
    TCPClient1.Active:=True;
  if TCPClient1.Connected then
  begin
    nRet := TcpClient1.SendBuf(buf,buflen);
    //もしSendBufの戻り値がマイナスであれば正常に
    //送信できていないのでその場合は、再送信などリトライを・・
    //無事送信できていれば、送信できたサイズを足しこむ
    nNowSendSize := nNowSendSize + nRet;
    if nNowSendSize >= nTotalsize then
    begin
      //無事にすべて送信できた
    end;
  end;
  TCPClient1.Active := False;
end;


挑戦者  2004-06-09 22:11:29  No: 9151

横槍失礼します。私も似たような事を悩みまして、結局こんな関数を作りました。
チャットクライアント用に作成したので、参考程度にどうぞ(汗
> データを送信する際に、送信が完了するまで、空ループを行いたいのですが
SendTextでいいのなら、固まる さんのやりたい事は満たしていると思います。
全てを送信完了するか、又は接続が途切れるまでループして強制的に送信、
無事に送信し終わったら0が、できなかった場合は残りのbyte数が返ります。
function TForm1.SendLog(LOG: string) : Integer;
var
i: Integer;
begin
  while Length(LOG) > 0 do                // 空になるまでループ
    with ClientSocket1 do if Active then  // Socket接続中なら処理
    begin
      i := Socket.SendText(LOG);          // 送信(ibyte送信完了)
      Delete(LOG, 1, i);                  // 送信完了部分削除
    end else break;                       // 接続切れ⇒ループ離脱
  Result := Length(LOG);                  // 返却値:未送信byte数
end;


固まる  2004-06-15 23:18:04  No: 9152

いろいろ教えていただいてありがとうございます。
以下の関数を作ってみました。
スレッドを使わない格好悪いやり方かもしれませんが、
テストしてみたところ、なんとか送信できるようです。

//  ArBuf  … 送信データ
//  ArBytes… 送信バイト数
//  ArRetry… リトライ回数
function TcpSend(ArBuf: array of byte; ArBytes, ArRetry: Integer): Integer;
var
  i,x,UsInt :Integer;
begin
  i := 0;
  x := 0;
  repeat
    UsInt := TcpClient1.SendBuf(ArBuf[i], 1); // 1バイトづつ地道に送信
    if  1 = UsInt then begin Inc( i ); x := 0; end
                  else begin Inc( x ); end;
  until (i = (ArBytes)) or (x > ArRetry );
  if (i < (ArBytes))
  or (x >  ArRetry ) then Result := -1
                     else Result := 0;
end;
またお願いいたします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加