いつもお世話になっております。
VBのWinsock1コントロールには、送信処理が完了したときに発生する
SendComplete というイベントがあるのですが、
DelphiのInternetタブのTClientSocketコンポーネントには、
このイベントがないみたいです。
他のコンポーネントで送信処理が完了したときに発生するようなイベントがあるものはありますでしょうか。
また、DelphiでWinSockを使用するには、どのようにすればいいでしょうか。
やりたいことはと言えば、データを送信する際に、
送信が完了するまで、空ループを行いたいのですが、
TClientSocket で実現する方法がわからないのです。
参考になれば良いのですが・・
TClientSocketを使ってSendComplateイベントもどきを実装するには
送信先相手サーバへ何バイト送信する予定で実際何バイト無事送信できたか?
を比較するようにすれば、可能です。
TclientSocketのSendbufを使うと送信するバッファと送信サイズが
ほぼ固定化するのでその比較は楽です
TClientSocketのBytesSendプロパティをなぜ使わないのかというと
知らずにSendBufメソッドを使って送信バイトと送信できたバイト数を
比較していたからです(汗
すいません、よろしければサンプルプログラムを教えていただけないでしょうか。
また、SendBuf(var Buf; Count: Integer): Integer; メソッドの
引数 Buf は、どんな型の変数になりますか、(バイト配列なんかでもOKでしょうか)
すでに画面に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;
横槍失礼します。私も似たような事を悩みまして、結局こんな関数を作りました。
チャットクライアント用に作成したので、参考程度にどうぞ(汗
> データを送信する際に、送信が完了するまで、空ループを行いたいのですが
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;
いろいろ教えていただいてありがとうございます。
以下の関数を作ってみました。
スレッドを使わない格好悪いやり方かもしれませんが、
テストしてみたところ、なんとか送信できるようです。
// 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;
またお願いいたします。
ツイート | ![]() |