Operating System - OpenVMS
1827840 Members
1608 Online
109969 Solutions
New Discussion

Re: Multi Server and client - non blocking in C++ on VMS

 
Lai King Leung
Occasional Advisor

Multi Server and client - non blocking in C++ on VMS

Hi Guys

I'm trying to write a client server application in C++. Everything has to be non-blocking so I've opted for ASTs. I can get the code to work for a single listener single client, but add on another listener and werid things happen such as the wrong AST firing for a given instance.

I've attached the main socket class.

Also does anyone know what the URL for the C++ socket library on VMS is ?
11 REPLIES 11
Craig A Berry
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

I'm guessing here, but I bet you are assuming that when an AST fires it knows what C++ instance it is part of, or in other words that the AST observes the scope of a C++ class instance. If you are assuming that, it's not true; ASTs have process-wide scope and you typically pass a parameter to them so they know what data to operate on. Your AST routines don't accept any arguments, so it's hard to see how they could know what operation has completed. You don't provide the source to GetThisInstance(), so perhaps there is some magic in there to sort this out, but I can't think offhand of any way an AST could figure out what class instance was in scope when the $QIO was initiated. The comments in your code sound right when they talk about using a class pointer as an AST parameter, but it doesn't look to me like the code currently implements that.
Lai King Leung
Occasional Advisor

Re: Multi Server and client - non blocking in C++ on VMS

Craig

Everything you say is spot on - I don't pass a parameter into the AST - instead I assign a global parameter before issuing the QIO. You'll notice that there is always a pSock = socketPackage; assignment before a SYS$QIO is issued. All the GetThisInstance method does, is allow me to check the correct instance has been called - it just returns an integer value that I passed in when I created the object. In the case of the multi listener - I am finding that both readASTs fire when ONE client has sent data !!

When I passed the object pointer as a parameter into the AST I found that when the AST fired, the object pointer was somehow dereferenced and I kept getting an ACCVIO, hence I created a global pointer and assign it before a SYS$QIO. This seemes to work and I get back all the expected member data. If you have some example code of a QIO accepting an object pointer as a parameter and working please let me know and I'll try it out - perhaps you could also send me the exact compiling switches you use.
My Email address is lai_king_leung@hotmail.com

Many Thanks
Lai King

Craig A Berry
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

I'm afraid I don't have an example handy. The basic procedure, though, is to allocate your pSock structure just before you initiate a connection (or prepare to listen for one) and free it right after you disconnect. A pointer to that structure would then be your AST parameter. I don't think you want the structure to be global because then your different connections will trip over each other using the same data, and you definitely don't want the structure to be local because then it will be out of scope when the AST fires. HTH.
Lai King Leung
Occasional Advisor

Re: Multi Server and client - non blocking in C++ on VMS

Craig

Are you saying that when I do
pSock = socketPackage

I should be doing
pSock = malloc (sizeof(CsocketPackage)); Then pass pSock as the AST parameter ??

I'll give it a go this weekend.

When the AST fires and I have done everything I free the memory again !?
Craig A Berry
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

Lai King,

Yes, that's the general idea. Possibly you will have some data shared by all connections and that would need to be made global, but everything that is specific to the connection should be allocated, passed, and freed as you have described.
Lai King Leung
Occasional Advisor

Re: Multi Server and client - non blocking in C++ on VMS

Craig

Starting Listener on channel 224 instance 0
****** Connection established on chan 224 instance 0
Checking Listener 0
ReadLength: Issuing length read on chan 224 instance 0
Starting Listener on channel 240 instance 1
Checking Listener 1
****** Connection established on chan 240 instance 1
Checking Listener 0
Checking Listener 1
ReadLength: Issuing length read on chan 240 instance 1

I tried that but I still get the following error:

processReadLengthAST: Data arrived on channel 240 instance 1
processReadLengthAST: Length read completion problem <0> on channel 240
***** %NONAME-W-NOMSG, Message number 00000000
CloseLinkAST: Link now closed on connection 240
CloseLinkAST: Link now closed on connection (instance 1)
processReadLengthAST: Data arrived on channel 0 instance 1
processReadLengthAST: Length read aborted on channel 0 - third party has closed connection
DisconnectChannel: Close link problem


I start up 2 listeners - to distinguish them I have allocated unique instance numbers: the first listener starts up on instance 0-on a client connection the main program assigns a new channel No and starts up Listener 2 on instance 1. Now when Client 1 talks it should talk to listener 1 on instance 0, and client 2 should be talking only to listener 2 on instance 1. Instead what happens is I send something in client 1 and the AST for instance 1 (listener 2) responds with the above error !!! If I only send data on client 2 then both listener 1 and listener 2 read ASTs fire !!!!

I've attached the CSocketPackage class which is the child class of CSocketInterface. The CSocketPackage class contains all the call back functions. The idea was to keep all the VMS stuff in CSOcketInterface and to make CSocketPackage pure C++ so if we have to port in the near future I caould just replace CSocketInterface code.

Any ideas what is happening ?
Craig A Berry
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

Do you have two servers listening on the same port? If so, then of course they will both become active when any and all clients connect on that port. Remember, C++ class instances do not restrict the scope of external resources like sockets or ASTs. If you haven't done so already, look at the example at

sys$common:[syshlp.examples.tcpip]tcpip$tcp_server_qio.c

and also tcpip$tcp_client_qio.c in the same directory. It's in C, not C++, and it's done synchronously, but it should have everything you need. To make it asynchronous, just change the sys$qiow calls to sys$qio and add completion routines and parameters.
Lai King Leung
Occasional Advisor

Re: Multi Server and client - non blocking in C++ on VMS

Craig

I have seen the examples you refer to and I have to admit that in C I had no problems using QIO to write a listener supporting mulitple client connections.

I'm not sure I agree with your comment that both listeners on the same port and IP will always fire - as far as I understood a listener can support multiple clients on the same IP and port providing the Channel Number is different. This works in C !!! Your statement is implying that a single IP and PORT can only service one client connection and if you want to service more clients they all have to connect in on different Ports !!! Well like I say I have no problems in C it's just in C++ !!

I'm wondering if it is the way ASTs are stored and handled internally by VMS !! I do find it odd that I can pass in a "this" pointer and everything is fine, but when I pass it as an AST parameter and the AST fires, the "this" pointer has somehow become dereferenced even though the object still exists. Furthermore when the AST fires - I cannot access any of the member data in the object even though the AST is a method in the class !! Is as if the AST method exist in an world of its own !!!

Willem Grooters
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

Just wondering...
Do I understand correctly that you have a program running (detached, presumably) that polls a port? It might than be worthwhile to take a somewhat different approach - it might take a bit of overhead but could prevent the problem:
* Write the program to read from device SYS$NET (which will a BG device when active)
* Create a commandproceduree that runs this program
* Eventually create a user, having NETWORK access and sufficient quota and privileges to run this commandprocedure, and a login.com to set all specific, proces-local logicals, symbols etc.
* Define which IP-port should be used for communication. When activated, the commandprocedure should run there. here you also define:
- the commandprocedure (/FILE=), Beware, though, that is you use any logical, it should be defined /SYSTEM.
- the user under whose name it is activated (/USER=) (the just created one). In it's login directory, all logfiles will be written (one for each invokation!)
- Number of concurrent entities (/LIMIT=)

We used this because of the same problem that you described.
Willem Grooters
OpenVMS Developer & System Manager
Craig A Berry
Honored Contributor

Re: Multi Server and client - non blocking in C++ on VMS

Lai King,

No, I wasn't trying to say you can't have multiple clients -- it sounded to me like you have multiple servers listening on the same port. If that's not what's happening, my apologies.

On the "this" pointer being dereferenced. I'm not that familiar with C++ internals. You may need to use the debugger and/or compile to assembler to find out exactly what's going on there; could it be a volatile pointer that has gone out of scope by the time the AST fires?
Vouters
Advisor

Re: Multi Server and client - non blocking in C++ on VMS

Hi Lai,

I am not aware of any C++ socket class. Anyway, I beleive if it existed, that it would be based on C socket programming rather than on AST $QIOs. I remember in the previous topic you wrote to have pointed you to a TCP/IP QIO based client/server application in C. If you study well the code, you should notice that the channel in passed in the AST parameter to the AST routines (read_ast and write_ast). This is the way you should proceed in writing your C++ class; you might set the socket channel as a Class private variable. This way your ASTs should not mix between channels. Please do not use non-blocking TCP/IP sockets, as it is useless.
Hoping this might help you.