使用Delphi中的套接字使用缓冲区发送/接收文本

时间:2014-11-29 07:23:30

标签: sockets delphi text buffer delphi-7

所以我已经找到了一种方法来完成这项工作,但没有找到可行的解决方案。我正在尝试使用套接字将已从客户端插入备忘录的文本发送到服务器。不幸的是我无法使编码工作。这可能是我做错的愚蠢行为;但我不知道错误在哪里。我在服务器和客户端之间创建了一个稳定的连接,我可以使用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是一个很大的痛苦。 如果有人能帮助我开展这项工作,我将非常感激。

1 个答案:

答案 0 :(得分:0)

我在Indy上做了一个非常简单的TCP客户端和服务器示例。这很简单,甚至没有例外处理。

看看a repository at 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;