Solved

How to disconnect to a indy server?

Posted on 2006-07-10
23
964 Views
Last Modified: 2011-10-03
Hi!

I have a server application that from start to the end just sends data and then my client recives the data and plot it.
The problem is that the client should be able to disconnect at any time.
Right now if i disconnect during the sending the server throws a EIdSocketError and i catch it and disconnect,
but the problem is that if i then try to connect to the server again the server throws a EIdSocketError again so the
client cant connect unlees i restart the client application? I think this has to do with that the port number still is occupied.
I nead to know how to handle a "bad" disconnection.

Thanks
0
Comment
Question by:mikrodidakt
  • 11
  • 5
  • 4
  • +1
23 Comments
 
LVL 28

Expert Comment

by:ciuly
ID: 17071080
Hi mikrodidakt,

that is hard to say without seeing at least how the server and client "protocol" is set up.
so either post you code, or explain your protocol and implementation (if you are using threads, thread pool, etc)

Cheers!
0
 
LVL 10

Expert Comment

by:atul_parmar
ID: 17071219
I suggest,

before desconnecting your client, send a msg from client to the server that it is about to disconnect so that the server could stop sending the data to it can perform any clean ups if required.. Once, it is acknowledged and the cleanup is over, you can disconnect your client.
0
 

Author Comment

by:mikrodidakt
ID: 17071248
Hi!

Teh problem is that i dont have the server yet, But the information i got is that the server is just going to start sending the data over ethernet on specific port and my client is going to listen to that port and plot the values.
So i am writing a server that is simulating this.
I have also got it explained that the server will accept a disconnection at any time.
I just want my client to be able to connect again after a "bad disconnection", and i think that the problem is at the client side since it works if I restatart the client? My code is in C++ so if you think it would help I will post it.
0
 

Author Comment

by:mikrodidakt
ID: 17071258
By the way i am using the Indy 9 components and there is not that many C++ programmers that is using that so thoubht i would ask my question here instead.
0
 

Author Comment

by:mikrodidakt
ID: 17071268
atul_parmar you are talking about clean up, could you explain this clean up because the only clean up i am doing is disconnect?
0
 
LVL 10

Expert Comment

by:atul_parmar
ID: 17071325
I mean the server might expect some termination commands before you disconnect your client. If it is not the case, you can try DisconnectSocket method.

The problem seems that when you try to disconnect, some process is already using the port. it works after restarting the process gets terminated when you close the client.
0
 

Author Comment

by:mikrodidakt
ID: 17071415
I have already tryied DisconnectSocket and that did not help.

1)This is how the "protocol" works i start my client and my server.
2)The user click on connect button on the client and the server accepts the connection by sending a reply.
3)The server is starting to send data and the client is reciving the data and ploting it in realtime

At any time during the reciving the user could click on a stop button this stop button is disconnecting the client from the server and this is where i get the problem. I handle the exception that is thrown on the server side and the client side is just disconnecting.
But it should be possible to run step 2 and 3  again at any time after a disconnection. As it is now the client has to be restarted to be able to establish a connection to the server.

Thanks for your help!
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17071449
Do _not_ hide the exception...you are meant to let it happen
any unhandled exception in the OnExecute event is caught by indy, which then disconnects the client socket
e.g.
onexecute event...
try
  dostuff
except
  on E: exception do
  begin
      DisplayThisMessageInMyLog;
      RAISE; // this is important
  end;
end;
0
 
LVL 10

Expert Comment

by:atul_parmar
ID: 17071451
0
 

Author Comment

by:mikrodidakt
ID: 17071520
Ok i understand that the right way to do it is to send a message to the server telling it that now it is time to disconnect and that is fine, but the server that i will be using in the future will not accept a message that like that.
So i just want the client to be able to disconnect and connect in infiniti.
As i see it the client will be able to disconnect but for some reason the port on the client not the server is locked in some way, the reason i think so is that when i start my server (the server i am using is not the server that i will use later is is just a simple server that i have writen to simulate the finnal server) and then disconnect from it with the client i can not connect again without the  EIdSocketError trown. Even if i restart the server the exception is trown untill i restart the client.
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17077616
no really... let the exception happen on the server. indy uses exceptions a lot, they are not all meant to be handled by you. They let the server know that it has to disconnect the socket. You do not need to disconnect it manually in the server code.
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17077720
on the client, make sure you have NOT set the "boundport" property, only the port property
indy usually lets windows pick the next available port to use, but youcan specifically set it, or use a range with boundportmin and boundportmax

1 other thing, there are several ways to disconnect the socket. eg. for indy's ftp client
on indy 9 you may use
IdFtp1.DisconnectSocket;
on indy 10.0.5.2 you may use
IdFtp1.Socket.Close;
0
 

Author Comment

by:mikrodidakt
ID: 17079512
Ok I might not understand you TheRealLoki I did as you wat you wanted i let the exception "happen".
But i still cant reconnect to the server after i have disconnected in a "bad manner", the server just throws a the exception again until i restart my client then i get a connection and the server starts to send the packages.
0
 
LVL 28

Expert Comment

by:ciuly
ID: 17079565
why don't you post your code :) I'm sure we can help you faster that way ;)
0
 

Author Comment

by:mikrodidakt
ID: 17079770
void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
        try {
                VMes = static_cast<void *>(mes);
                LLine = AThread->Connection->ReadLn();
                LCmd = Fetch(LLine);

               if(AnsiSameText(LCmd, "SEND")) {
                        //----------------------ignore this------------------------
                        mes = (Message*) malloc(sizeof(Message));
                        mes->STX          = 0x0002;
                        mes->CRC          = 0x858E;
                        mes->MachID       = 0x000A;
                        mes->ClinicalSWID = 0x0064;
                        mes->MsgCounter   = 0x00000000;
                        mes->CmdCode      = 0x00000000;
                        mes->MsgInfo      = 0x00000066;
                        mes->Flags        = 0x00000002;
                        mes->PatId        = 0x000004BC;
                        mes->records[0].Param_code    = 0x00000005;
                        mes->records[0].Time          = 0x437CA428;
                        mes->records[0].Measure_Value = 0x000004C8;
                        mes->records[1].Param_code    = 0x00000001;
                        mes->records[1].Time          = 0x437CA428;
                        mes->records[1].Measure_Value = 0xFFFFFFD4;
                        mes->records[2].Param_code    = 0x00000002;
                        mes->records[2].Time          = 0x437CA428;
                        mes->records[2].Measure_Value = 0x00000059;
                        mes->records[3].Param_code    = 0x00000003;
                        mes->records[3].Time          = 0x437CA428;
                        mes->records[3].Measure_Value = 0xFFFFFFFE;
                        mes->records[4].Param_code    = 0x00000004;
                        mes->records[4].Time          = 0x437CA428;
                        mes->records[4].Measure_Value = 0x00000022;
                        mes->records[5].Param_code    = 0x00000005;
                        mes->records[5].Time          = 0x437CA428;
                        mes->records[5].Measure_Value = 0x00000000;
                        mes->records[6].Param_code    = 0x00000006;
                        mes->records[6].Time          = 0x437CA428;
                        mes->records[6].Measure_Value = 0x0000003E;
                        mes->records[7].Param_code    = 0x00000007;
                        mes->records[7].Time          = 0x437CA428;
                        mes->records[7].Measure_Value = 0x0000001F;
                        //-------------------------------------------------------------------
                        int y = 0;
                        while(y < 1000){
                                mes->records[2].Time++;
                                randomize();
                                mes->records[2].Measure_Value = 10*sin((random(100)%10)/3);
                               
                                Idglobal::Sleep(500);
                                ++y;
                                VMes = static_cast<void *>(mes);
                                long int PktSize = sizeof(*mes);
                                AThread->Connection->WriteBuffer(VMes, PktSize);
                        }
                }
        } catch(EIdConnClosedGracefully& e) {
                AThread->Connection->Disconnect();
                Memo1->Lines->Add("Connection Closed");
        }
       /*
       catch(EIdSocketError& e) {
                AThread->Connection->Disconnect();
                Memo1->Lines->Add("Connection Closed");
        }  
       */
}
0
 

Author Comment

by:mikrodidakt
ID: 17079792
On the client side

void __fastcall TForm1::ConnectButtonClick(TObject *Sender)
{
        GraphHandler gh(*Series1, *Chart1, *ChartEditor1);
        MessageHandler mh;
        Message* mes;
        void* VMes = (void*) malloc(sizeof(*mes));

        short response = 200;
        bool first_mess = true;
        ConnectButton->Enabled = false;
        lboxResult->Clear();
        this->Series1->Clear();
        try{
            try{
                TCPConn->Connect();
                this->StatusBar1->SimpleText = "  Starting to processing recived data....";
                TCPConn->GetResponse(&response, sizeof(response));
                lboxResult->Items->AddStrings(TCPConn->LastCmdResult->Text);
                lboxResult->Items->Add("");

                TCPConn->WriteLn("SEND");
                while(run) {
                        TCPConn->ReadBuffer(VMes,sizeof(*mes));
                        mes = static_cast<Message*>(VMes);
                        mh.recvData(mes);
                        if(first_mess){
                             first_mess = false;
                             mh.getStartDateTime(*(this->Edit2));
                        }
                        if(mh.checkCRC()) {
                                gh.plot(mh, this->Series1);
                                Chart1->Update();
                        }
                }
            } catch(EIdConnClosedGracefully& e) {
                lboxResult->Items->Add("caught EIdConnClosedGracefully");
            }
        }__finally {
                if(TCPConn->Connected()){
                        TCPConn->Disconnect();
                        lboxResult->Items->Add("Disconnected");
                        this->StatusBar1->SimpleText = "";
                        TCPConn->DisconnectSocket();
                }
                free(VMes);
                ConnectButton->Enabled = true;
                this->StatusBar1->SimpleText = "  Stopped!";
        }
}
The stop button could be click on at any time
void __fastcall TForm1::stopButtonClick(TObject *Sender)
{
        run = false;
        this->StatusBar1->SimpleText = "  Stopped!";
}
0
 

Author Comment

by:mikrodidakt
ID: 17079796
I have increased the point value
0
 
LVL 28

Expert Comment

by:ciuly
ID: 17079916
I am just curious: if you are doing this all in borland C, why did you post on delphi?
0
 

Author Comment

by:mikrodidakt
ID: 17081779
Because the documentationon for indy is not that god for C++builder. But i think it is the best commponent for TCP.
And even if there is some problems for me as a C++programmer to understand everything in Delphi the basic is the same.
I have put some questions in C++ forum but there is not that many that is using Indy as it is in Delphi so i thought i ought to try the Delphi forum.
This question might have got a bit to big so i thank every one for there time and if no one have posted any new
comments by tommorow i will delete this.

Thanks every one for your time.

 
0
 
LVL 28

Expert Comment

by:ciuly
ID: 17081993
I looked over the client code, and
                while(run) {
seems like a dead end at least in delphi.

when you click on a button and have an semi-infinite cycle in it without an application.processmessages, it will run forever.
check such cycles, and try to avoid them. better use a trhead instead of that while thing in the vcl thread. it's too ugly and hard to control if you don't know vcl well enough
0
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 500 total points
ID: 17084970
ah the plot thickens
well i don't know much about c++ builder but this should do the trick anyway

dynamically create the TCPConn in your button click, and free it at the end
this will reliably clean up the used socket port
I'll use a mix of delphi and c++ code, but you should be able to work it out
var
    TCPConn: TidTCPClient;
begin
  TCPConn := TidTCPClient.create(nil)
  TCPConn.port := 2000;
  TCPConn.host := 'localhost';
  try
      try{
            try{
                TCPConn->Connect();

.. other code here

            } catch(EIdConnClosedGracefully& e) {
                lboxResult->Items->Add("caught EIdConnClosedGracefully");
            }
        }__finally {
                if(TCPConn->Connected()){
                        TCPConn->Disconnect();
                        lboxResult->Items->Add("Disconnected");
                        this->StatusBar1->SimpleText = "";
                        TCPConn->DisconnectSocket();
                }
        }

  finally
    TCPConn.Free; // get rid of it
  end;
0
 

Author Comment

by:mikrodidakt
ID: 17088413
That might work but will TAntiFreeze component work then?
I will give you the points TheRealLoki.
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17088657
should do, the TidTCPClient components (etc) "self - registers" themselves with the TidAntiFreeze
but just to be safe, do TCPConn := TidTCPClient.create(Form1) instead of (nil)
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

744 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now