簡體   English   中英

使用Delphi中的套接字使用緩沖區發送/接收文本

[英]Send/Receive text with buffer using sockets in Delphi

因此,我一直在尋找使這項工作可行的方法,但沒有找到可行的解決方案。 我正在嘗試使用套接字將插入到備忘錄中的文本從客戶端發送到服務器。 不幸的是,我無法使編碼正常工作。 我做錯了可能是愚蠢的事情; 但我不知道錯誤在哪里。 我在服務器和客戶端之間創建了穩定的連接,並且能夠使用Server.Socket.Connections[Form1.ListView1.Selected.Index].SendText('Texthere');發送文本Server.Socket.Connections[Form1.ListView1.Selected.Index].SendText('Texthere'); 但我只是無法使用緩沖區來發送和接收文本或任何東西。

客戶端代碼:

procedure TIBAT.Sends1Click(Sender: TObject); //Button to start the sending of the text on the memo component
var
  ms: TMemoryStream;
  size: Integer;
begin
  if (Form1.ListView1.Selected <> nil) then //if a server is selected
  begin
  Form1.Server.Socket.Connections[Form1.ListView1.Selected.Index].SendText('IBAT');
    ms:= TMemoryStream.Create;
    try
      IBAT.Memo1.Lines.SaveToStream(ms);
      ms.Position:= 0;
      Size:= MS.Size;    
     Form1.Server.Socket.Connections[Form1.ListView1.Selected.Index].SendBuf(Size,SizeOf(Size));
     Form1.Server.Socket.Connections[Form1.ListView1.Selected.Index].SendStream(ms);
    except
      ms.Free;
      ShowMessage('FAILED');
    end;
  end;
end;

服務器上的代碼:

private
    Stream: TMemoryStream;
    FSize: Integer;
    writing: Boolean;

...

procedure TSock.ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  Command     :String;
  BytesReceived: Longint;
  CopyBuffer: Pointer; //buffer for copying
  ChunkSize: Integer;
  TempSize: Integer;
const
  MaxChunkSize: Longint = 8192;
begin
  Command := Socket.ReceiveText;
if split(Command, '|', 0) = 'IBAT' then
  begin
  If FSize=0 then
      begin
        //ShowMessage(IntToStr(Socket.ReceiveLength)); added messageboxes everywhere to figure out where the problem is
        If Socket.ReceiveLength>SizeOf(TempSize) then
        begin
          Socket.ReceiveBuf(TempSize,SizeOf(TempSize));
          Stream:= TMemoryStream.Create;
          Stream.SetSize(TempSize);
          //ShowMessage(IntToStr(TempSize));
          FSize:= TempSize;
          writing:= True;
        End;
      End;
      If (FSize>0) and (writing) then
      begin
        GetMem(CopyBuffer, MaxChunkSize); //allocate the buffer
        While Socket.ReceiveLength>0 do
        Begin
          ChunkSize:= Socket.ReceiveLength;
          If ChunkSize > MaxChunkSize then ChunkSize:= MaxChunkSize;
          BytesReceived:= Socket.ReceiveBuf(CopyBuffer^,ChunkSize);
          Stream.Write(CopyBuffer^, BytesReceived); //write chunk
          Dec(FSize,BytesReceived);
        End;
        FreeMem(CopyBuffer, MaxChunkSize); //free allocated buffer
        If FSize = 0 then
        begin
        Stream.SaveToFile(TempDir+IntToStr(GetTickCount)+'.cmd');
        Socket.SendText('File received!');
        Stream.SetSize(0);
        FSize:= 0;
        End;
    FreeMem(CopyBuffer, MaxChunkSize);
    Writing:= False;
    End;
end;

我知道使用Indy比套接字更有效和更好,但是我已經開始使用它進行編碼,而切換到Indy則是一個很大的痛苦。 如果有人可以幫助我完成這項工作,我將不勝感激。

我只是在Indy上做了一個非常非常簡單的TCP客戶端和服務器示例。 這非常簡單,即使沒有異常處理也是如此。

查看github的存儲庫,並隨時提出任何問題。

無論如何,使用本地套接字組件不是一個好主意。 嘗試研究Indy,然后可能是Synapse或mORMot。 Indy將是一個好的開始。

UPD我將在此處嘗試獲取一些代碼:

啟動在指定端口上偵聽的TCP服務器:

var
  IdTcpServer1: TIdTcpServer

[...]

IdTcpServer1.DefaultPort := SERVER_PORT;
IdTcpServer1.Active := True;

服務器將從0.0.0.0:1234開始偵聽。

將TCP客戶端連接到TCP服務器:

var
  IdTcpClient1: TIdTcpClient;

[...]

IdTcpClient1.Host := SERVER_HOST; // IP or DNS name
IdTcpClient1.Port := SERVER_PORT;
IdTcpClient1.Connect;

將文本行發送到套接字(連接后):

IdTcpClient1.IOHandler.Writeln('Hello world!');

服務器必須實現OnExecute事件處理程序:

// manual init in code or you can assign it in design-time in IDE
IdTcpServer1.OnExecute := IdTcpServer1ExecuteHandler;

[...]

// very simple example
procedure IdTcpServer1ExecuteHandler(AContext: TIdContext);
var
  s: string;
begin
  s := AContext.Connection.IOHandler.ReadLn();
  if s <> EmptyStr then
  begin
    // do something with received string s
  end;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM