Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 360
  • Last Modified:

What is going wrong in my connection?

Hi,
I'm writing this Client Server program, the server sends images to a client. And the client can send commands to the server, commands of 1 byte long.
Later on, server should also be able to send a stream of other bytes, but that doesn't matter right now.
I use a blocking connection, and on both sides (also on the client side) I use a thread to read from the TWinSocketStream.
The code bellow works for the first image, when I connect the client with the server, a first image is send, the size (of the image) is recieved correctly, and then the rest of the image is also recieved correctly.
Then I can use my client to send commands, the server recieves them correctly, that works just fine. But then, when I want to send a second image. I first fill the buffer of the DataStream and afther that I put the ReadyToSend property on true. Then the ClientThread in the server sees that that property is true and first tries to send the size, he sends it correct, but on the client side a total diff. nr is recieved, and my whole client system goes down (of course, he is waiting for data that isn't coming).
Can u have a look at my code and tell me what I'm doing wrong? Cause I just can't find it, I tried different things but it just ain't working the second time.

In the serverthreads:
procedure TServerThread.ClientExecute;
const
    MAXBUFSIZE = 1024;
var Cmd: Byte;
    Stream: TWinSocketStream;
    Dummy: TMemoryStream;
    ImgSize: integer;
    Buf: PByteArray;
    Result: integer;

begin
Stream := TWinSocketStream.Create(ClientSocket,1000);
Dummy:=TMemoryStream.Create;
DiscReason:='No specified reason.';
Synchronize(SetConnected);
try
while NOT(Terminated) do begin
sleep(0);
if uServer.Form1.DataStream.ReadyToSend=true then begin
    uServer.Form1.DataStream.ReadyToSend:=false;
    ImgSize:=uServer.Form1.DataStream.Size;
    aMessage:='Sending size: '+IntToStr(ImgSize);
    Synchronize(PostMessage);
    Result:=Stream.Write(ImgSize,SizeOf(ImgSize));
    aMessage:='Sended bytes from the int:'+IntToStr(Result);
    Synchronize(PostMessage);
    Dummy.Clear;
    Dummy.LoadFromStream(uServer.Form1.DataStream);
    Dummy.SaveToStream(Stream);
    aMessage:='Succesfully send image.'+IntToStr(ImgSize);
    Synchronize(PostMessage);
    end;
if Stream.Read(Cmd,SizeOf(Cmd))<>0 then begin
    if Cmd=10 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Right') else
    if Cmd=11 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Left') else
    if Cmd=12 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Up') else
    if Cmd=13 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Down') else
    uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Huh?')
    end;
end;
except
    DiscReason:='Exception';
end;
    Synchronize(SetDisConnected);
end;

-----

In my Client program:
procedure TClientThread.Execute;
const
    MAXBUFSIZE = 50;
var
    Stream: TWinSocketStream;
    BufSize, BytesRead, Result, Count: Integer;
    ImgSize: ^Integer;
    B:Byte;
    Buf: PByteArray;
    IntBuffer: array[0..3] of Byte;
begin
Stream:=TWinSocketStream.Create(uClient.Form1.ClientSocket1.Socket,60000);
Stream.TimeOut:=50;
Dummy:=TMemorystream.Create;
DiscReason:='No specific reason.';
Synchronize(SetConnected);
while (uClient.Form1.ClientSocket1.Active) and (NOT(Terminated)) do begin
    sleep(0);
    try
    Count:=0;
    if Stream.Read(B,1)=1 then begin
        aMessage:='Recieving pic!';
        Synchronize(PostMessage);
        IntBuffer[Count]:=B;
        Count:=1;
        repeat
            if Stream.Read(B,1)=1 then begin
                IntBuffer[Count]:=B;
                Inc(Count,1);
                end;
        until Count=4; // Nu hebt ge een volledige integer ingelezen (4 bytes)
        ImgSize:=Addr(IntBuffer[0]);
        aMessage:='Size='+IntToStr(ImgSize^);
        Synchronize(PostMessage);
        repeat
            if ImgSize^ > MAXBUFSIZE then BufSize:=MAXBUFSIZE else BufSize:=ImgSize^;
            GetMem(Buf,BufSize);
            BytesRead:=Stream.Read(Buf^,BufSize);
            Dummy.Write(Buf^,BytesRead);
            Dec(ImgSize^,BytesRead);
        until ImgSize^=0;
        Dummy.Position:=0;
        aMessage:='Recieved bytes: '+IntToStr(Dummy.Size);
        Synchronize(PostMessage);
        uClient.Form1.Image1.Picture.Bitmap.LoadFromStream(Dummy);
        Dummy.Clear;
        IntBuffer[0]:=0;
        IntBuffer[1]:=0;
        IntBuffer[2]:=0;
        IntBuffer[3]:=0;
    end;
    Stream.TimeOut:=50; //50 msec voor 1 commando
    if Cmd.ReadyToSend=true then begin
        if Stream.Write(Cmd.Cmd,1)=0 then begin
            DiscReason:='Time out on command write';
            Terminate;
            end;
        Cmd.ReadyToSend:=false;
        end;
    except
    Terminate;
    end;
    end;
Synchronize(SetDisconnected);
uClient.Form1.ClientSocket1.Active:=false;
end;

Hope u can help.
HaCo
0
HaCo
Asked:
HaCo
  • 3
  • 3
  • 2
  • +1
1 Solution
 
mocartsCommented:
first, you have a memory leak in client portion of code:
...
       repeat
           if ImgSize^ > MAXBUFSIZE then BufSize:=MAXBUFSIZE else BufSize:=ImgSize^;
          // here! you allocate memory, but not free it
           GetMem(Buf,BufSize);
           BytesRead:=Stream.Read(Buf^,BufSize);
           Dummy.Write(Buf^,BytesRead);
           Dec(ImgSize^,BytesRead);
       until ImgSize^=0;

and it's better to allocate buffer outside the loop

if ImgSize^ > MAXBUFSIZE then BufSize:=MAXBUFSIZE else BufSize:=ImgSize^;
GetMem(Buf,BufSize);
try
  repeat
  ...
  until ImgSize^=0;
finally
  FreeMem(Buf, BufSize);
end;

and you could use WaitForData to check whether connection is ready to read:

var
  ImgSize: integer;
begin
..
if Stream.WaitForData(1000) then begin
  BytesRead := Stream.Read(ImgSize, sizeOf(Integer));
  if BytesRead = 0 then Terminate; // connection reset by peer or no network or etc.;
 ..
end;

this must be synchronize()'d:
uClient.Form1.Image1.Picture.Bitmap.LoadFromStream(Dummy);

// better provide thread with property Socket and assign it when create the Thread;
th := TClientThread.Create(True); // create suspended
th.Socket := ClientSocket1.Socket;
th.Execute;
// and in thread use
Stream:=TWinSocketStream.Create(FSocket,60000);

wbr, mo.
0
 
HaCoAuthor Commented:
Ok, I did the most of the things u said, but the waitfordata allways returns falls here. I tested it just in front of my while loop in the thread of my Client connection, and it return false.
Any idea why?
0
 
krukmatCommented:
Comment this line on the client:
  Stream.TimeOut:=50;
And try again.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
mocartsCommented:
WaitForData(..) returns true only if there is incoming data on connection.
you must use it inside the loop.

while (uClient.Form1.ClientSocket1.Active) and (NOT(Terminated)) do begin
  try
  if Stream.WaitForData(1000) then begin
    aMessage:='Recieving pic!';
    Synchronize(PostMessage);
    BytesRead := Stream.Read(ImgSize, sizeOf(Integer));
   
    if (BytesRead = 0) then Terminate; // connection reset by peer or no network or etc.;
   
    aMessage:='Size='+IntToStr(ImgSize^);
    Synchronize(PostMessage);
    if ImgSize > MAXBUFSIZE then BufSize:=MAXBUFSIZE else BufSize:=ImgSize;
    GetMem(Buf,BufSize);
    try
    repeat
      BytesRead:=Stream.Read(Buf^, BufSize);
      Dummy.Write(Buf^, BytesRead);
      Dec(ImgSize, BytesRead);    
    until ImgSize = 0;
    finally
      FreeMem(Buf, BufSize);
    end;
    Dummy.Position:=0;
    aMessage:='Recieved bytes: '+IntToStr(Dummy.Size);
    Synchronize(PostMessage);
    Synchronize(LoadImageFromDummy);
    Dummy.Clear;
  end;
  ..
end; // while not Terminated etc.

and in server portion of code where you look for data after image sent - you also need to use WaitForData:

if Stream.WaitForData(100) then begin
   Result := Stream.Read(Cmd, SizeOf(Cmd));
   if Result = 0 then Terminate; // disconnected etc.

   if Cmd=10 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Right') else
   if Cmd=11 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Left') else
   if Cmd=12 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Up') else
   if Cmd=13 then uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Down') else
   uServer.Form1.Memo1.Lines.Add(ClientSocket.RemoteAddress+': Huh?')
   end;
end;

wbr, mo.

0
 
HaCoAuthor Commented:
Tried it, doesn't help. Why is the WaitForData good for anyway? If I do Stream.Read(Buf,Count); then the socket waits until Timeout to read Count data, it is possible that it doesn't read all, therefor it returns the amount of data that was read. And my code works perfectly for the first image.
When I send the second image it goes all wrong. Even if I only send the size of the Image (an Integer), even that isn't recieved right. I don't know why. The client only recieves 1 byte from the integer and that's it.
Very Strange
0
 
mocartsCommented:
waitForData waits while data for receiving is sent or timeout occurs, but without data reading. that means you don't need such IntBuffer array and hard to understand and use construction.

and krukmat is right in his comment. you can set Stream.TimeOut := 50; but don't forget to set it back to previous 1000 (1sec) - either you never get more than one byte after first loop;

wbr, mo.
0
 
krukmatCommented:
try comment the line i sugeested you and try with method
WaitForData(...).
0
 
HaCoAuthor Commented:
It's not working.
I also don't really have the time to wait. I want to send +/- 2 images of 5kb per second over a LAN. It is so strange that I don't recieve the right data. When I send the second image, then in the while loop op my Client I recieve (at least) 1 byte, but that's it. And it's a wrong one. Why do I recieve wrong data?
I don't get it.
0
 
CleanupPingCommented:
HaCo:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now