• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 6731
  • Last Modified:

Blocking vs. NonBlocking with TTCPClient

I would like to understand the principle. What is the difference between blocking and nonblocking TCP connection? How is the data flow handled? What are the points to be considered when deciding to use one the ways?
Would appreciate a client code sample for downloading a HTML page with both approaches.
BTW: for Delphi 7.
0
Vihmapuu
Asked:
Vihmapuu
  • 4
  • 3
  • 2
  • +1
2 Solutions
 
Wim ten BrinkCommented:
The principle is quite simple. In blocking mode, you send some command to the other server and you stop doing anything else until the server responds. In non-blocking mode you send a command and just continue doing whatever you need to do. Sooner or later the server will send you a response and an event gets triggered notifying you about the command you've received.

In general, people either choose to use a non-blocking technique since it allows your code to just continue running. However, in some situations you cannot continue unless you've received the full response from the server thus you would have to choose blocking mode. But in the latter case, you better create a multi-threaded application, where the main thread will keep your GUI alive while the thread that makes the request will be blocked until an answer has been received.

The Indy 9 components don't seem to support non-blocking mode, though. I could be mistaken but I've never even used them in non-blocking mode. I just use multiple threads, one to read data and the other to write data.
0
 
VihmapuuAuthor Commented:
Thanks for explaining the principle. Any samples for both modes?
0
 
tobjectpascalCommented:
indy has one, so does borland, i prefer the tcpclient which sits in the internet tab.

i never have liked indy, i just could not get used to it, instead i create my own class of tthread and created a socket (blocking) with tcpclient.

probably (without checking) the main reason why indy only supports blocking is simply due to the fact linux does not support asynchronous sockets, only windows.. in windows what happens is that you can specify that winsock notifiys you of the data and posts a message to  your application with fd_read, fd_close, whatever, but somewhere in the background the winsock dll is actually doing this in a thread and sending out messages when it's finished, in linux, you don't have that type of system, so you have to do that yourself.

depending on the task in hand, for example getting a webpage, it's make a connection, send off the header to request a webpage, read read read until finished then the server closes the socket, you exit the loop and the thread terminates.. you can keep all the code in a couple of little procedures where it's

connect

sendheader

while(incomingdata=true)
  Begin
     stick all the data into a buffer or just save it to disk
  End;

exit;


with async, it's a lot more "messy" you would have to do.. connect.

onconnect
  sendheader

onrecv
  data:=data+data; or something

ondisconnect
  disconnected;

onerror
  handle any problems

soon enough you end up with 4 or 5 procedures where you have to declare vars to handle this data all over the place, esp for a webpage or downloading a file...

so i tend to use async sockets for things that are going to be connected for a while, like chat servers, messaging servers, anything that needs to stay on for a long time, then use non blocking, if it's short and sweet or of a stream which means a continuous flow of data, then use blocking and thread it.

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
tobjectpascalCommented:
ok this probably will not work straight off, i wrote my own tcpclient clone using winsock here's an example of how blocking sockets work.

what this example does is goes to www.whatismyip.com and requests the IP, it then gets the data, parses out your IP and returns it.. you will have to take out some code because i ripped this straight out of y!mlite

http://daynacommunications.com/ymlite my chat client for yahoo.


Type TwhatIsMyIP = Class (TThread)
  Port,Server: String;
  HttpStr: String;
  Data: String;
  Count: Integer;
  Socket: TDCBSock;
  Procedure Execute; Override;
  Procedure OnDisconnect;
  Constructor Create(SSearchStr,SUser: String; SCount: Integer);
End;


{ TWhatIsMyIP }

constructor TWhatIsMyIP.Create;
begin
 Inherited Create(false);
end;

procedure TWhatIsMyIP.Execute;
Var
 S: String;
 N,Br: Integer;
begin
 Data:='';
 Socket:=TDCBSock.Create(Nil);
 Socket.BlockMode:=BmBlocking;
 Socket.RemoteHost:='www.whatismyip.com';
 Socket.RemotePort:='80';
 HttpStr:='GET / HTTP/1.1'+CrLf+'Accept: */*'+CrLf+'Accept-Language: en-us'+CrLf+'Host: www.whatismyip.com'+CrLf+'Connection: close'+CrLf+CrLf;
 Socket.Connect;
 Sleep(40);
 If Socket.Connected=True Then
  Try
    Socket.Sendln(HttpStr);
    Data:='';
     While (Socket.WaitForData(10000)) Do
      Begin
        S:=Socket.Receiveln;
        BR:=Socket.BytesReceived;
        Data:=Data+S;
        Application.ProcessMessages;
      End;
     OnDisconnect;
   Except
    Socket.Disconnect;
   End;
 Socket.Free;
end;

procedure TWhatIsMyIP.OnDisconnect;
Var
 Title,Des,Url,BuildStr,TmpStr: String;
 C,P1,P2: Integer;
begin
  C:=0;
  TmpStr:=Data;
//  Form1.Memo2.Text:=TmpStr;
  If Data='' Then Exit;
  BuildStr:=Form1.ExtractBetweenString('<TITLE>','</TITLE>',Data,True);
  Form1.Richedit1.Lines.Add(BuildStr);
    If Trim(GmyIP)='' Then
      If MessageDlg('Want to set this IP to the Global IP Address? ',MtConfirmation,[mbyes,mbno],0)=IDYes Then
      Begin
        Delete(BuildStr,1,11);
        BuildStr:=Copy(BuildStr,1,Pos(' ',BuildStr)-1);
        GMyIp:=BuildStr;
      End;
end;
0
 
Mohammed NasmanSoftware DeveloperCommented:
http://www.swissdelphicenter.ch/en/indyarticles.php

read the article Introduction to Indy
0
 
VihmapuuAuthor Commented:
Well, I was able to make the blocking version work all right.
But the non-blocking does not even get to the Connect event. Why? What is the correct code for making TTCPClient of Delphi 7 work in non-blocking mode?
0
 
VihmapuuAuthor Commented:
Actually, in NonBlocking mode it goes to OnError and gives 10035 error, while the same with Blocking works fine.
0
 
Wim ten BrinkCommented:
Actually, the non-blocking mode is just similar to the blocking mode, except that the system is using a different thread to wait for a reply.
With non-blocking mode you need to have a separate thread just to keep an eye on the connection and to wait for a response. Once a response is detected, it is retrieved and the thread synchronizes with the main thread so the response can be processed.

Francois Piette has created ICS, a component set for both blocking and non-blocking TCP/IP connections at http://www.overbyte.be which used to be quite popular before Borland added Indy to Delphi. ICS is still a very good component set but it's just that Indy has gained a lot more popularity.
0
 
VihmapuuAuthor Commented:
Since no real samples were provides, I rated as Average. Nobody showed how to make NonBlocking mode work with TTCPClient.
The principle was explained well, though.
0
 
tobjectpascalCommented:
i've tried with TTCPClient, it does not beahve correctly, install TClientSocket

Delphi Menu > Components > install packages

C:\Program Files\Borland\Delphi7\Bin\dclsockets70.bpl


then async/non blocking will work exactly how it should, i don't think the event handlers were setup properly to allow nonblocking with that component, i had problems that's all i remember.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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