So I have searched for a way to make this work but found no working solution. I am trying to send text that has been inserted in to a memo from the Client to the Server using sockets. Unfortunately I cannot get the coding working. It might be something stupid I'm doing wrong; but I don't know where the mistake is. I created a stable connection between the server and client, and I am able to send text using Server.Socket.Connections[Form1.ListView1.Selected.Index].SendText('Texthere');
but I just cant get it to send and receive text or anything using buffers.
Code on Client:
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;
Code on the Server:
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;
I know using Indy is more effective and better than sockets, but I've already started coding using it and switching over to Indy is a big pain. If anyone can help me get this working I would really appreciate it.
I've just make a very-very simple example of TCP client and server on Indy. It is very simple, even no exceptions handling there.
Take a look at a repository at github and feel free to ask any questions.
Anyway, using of native socket components is not a good idea. Try to study Indy, then Synapse or mORMot may be. Indy will be a good start.
UPD I'll try to get some code here in answer:
Start a TCP server listening on specified port:
var
IdTcpServer1: TIdTcpServer
[...]
IdTcpServer1.DefaultPort := SERVER_PORT;
IdTcpServer1.Active := True;
Server will start listening on 0.0.0.0:1234.
Connect a TCP client to TCP server:
var
IdTcpClient1: TIdTcpClient;
[...]
IdTcpClient1.Host := SERVER_HOST; // IP or DNS name
IdTcpClient1.Port := SERVER_PORT;
IdTcpClient1.Connect;
Send a text line to socket (after it's connected):
IdTcpClient1.IOHandler.Writeln('Hello world!');
Server must implement OnExecute
event handler:
// 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;