?
Solved

What is going wrong in my connection?

Posted on 2003-02-24
9
Medium Priority
?
350 Views
Last Modified: 2010-04-04
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
Comment
Question by:HaCo
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 9

Expert Comment

by:mocarts
ID: 8007547
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
 

Author Comment

by:HaCo
ID: 8007936
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
 
LVL 1

Expert Comment

by:krukmat
ID: 8007984
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.

 
LVL 9

Accepted Solution

by:
mocarts earned 150 total points
ID: 8008026
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
 

Author Comment

by:HaCo
ID: 8008064
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
 
LVL 9

Expert Comment

by:mocarts
ID: 8008429
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
 
LVL 1

Expert Comment

by:krukmat
ID: 8008720
try comment the line i sugeested you and try with method
WaitForData(...).
0
 

Author Comment

by:HaCo
ID: 8014735
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
 

Expert Comment

by:CleanupPing
ID: 9317099
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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses
Course of the Month14 days, 4 hours left to enroll

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question