Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

please check this code

Status
Not open for further replies.

ariftheruvath

Programmer
Sep 13, 2012
19
0
0
AE

i'm using 2 winsock control (winsock.ocx)
1= 'rmtlisten1' handling connection request from client listening to port '9999'
2= 'LIC' which is already stored in object array and the state= 'listening' to available port

it is working well but if the users conneced (ie the no of accepted connection reaches 10 ) it gives an error msg 'In sufficient memory'




****** * D:\MIS\MISSERVER.SCX
Top = 0
Left = 0
Width = 0
Height = 0
Datasource = .Null.
Name = "Dataenvironment"
Top = 25
Left = 0
Height = 386
Width = 442
DoCreate = .T.
Caption = "MIS Server"
ControlBox = .F.
Closable = .F.
Name = "frmServer"
Procedure Init

abcd=Inputbox('Local Port','MisServer Port','9999')

srvport=Val(abcd)&& load this from config File REcommended
Thisform.rmtlisten1.janal.Object.LocalPort = srvport
Thisform.rmtlisten1.janal.Object.Listen
lstport=Thisform.rmtlisten1.janal.Object.LocalPort
This.label1.Caption='Listening to Port : '+Alltrim(Str(lstport))+Chr(13)
This.label2.Caption='Max Users : '+Alltrim(Str(MAX_USERS))+ Chr(13)
Public Array licarray(MAX_USERS)
For i=1 To Alen(licarray)
***create obj array
licarray(i)=Createobject('lic')
licarray(i).janal.Object.LocalPort=0
licarray(i).janal.Object.Listen
licarray(i).Comment=licstring
Endfor

Endif

Endproc


Top = 0
Left = 408
Visible = .F.
Name = "Rmtlisten1"
janal.Top = 0
janal.Left = 0
janal.Height = 100
janal.Width = 100
janal.Name = "janal"
Procedure janal.ConnectionRequest
*** ActiveX Control Event ***
Lparameters requestid
*sckClosed =0 &&Default. Closed
*sckOpen =1 &&Open
*sckListening =2 &&Listening
*sckConnectionPending =3 &&Connection pending
*sckResolvingHost =4 &&Resolving host
*sckHostResolved =5 &&Host resolved
*sckConnecting =6 &&Connecting
*sckConnected =7 &&Connected
*sckClosing =8 &&Peer is closing the connection
*sckError =9 &&Error

If Type('licarray',1)=='A'
***count Users connected already
x=0
For i=1 To MAX_USERS
If licarray(i).janal.Object.state=7 && if connected
x=x+1
Endif
Endfor
Thisform.label3.Caption="Users connected : "+Alltrim(Str(x))
If x=MAX_USERS
Else
**Accept connection to First available socket
For i=1 To MAX_USERS
If licarray(i).janal.Object.state=7
Else
licarray(i).janal.ConnectionRequest(requestid)
Exit
Endif
Endfor
Endif

Endif

Endproc





Procedure ConnectionRequest && Winsock Control ' LIC'
*** ActiveX Control Event ***
Lparameters requestid
This.Object.Close()
*IF THIS.OBJECT.State<>7
This.Object.Accept(requestid)
If This.Object.state=7 && CONNECTED

****code***
Endif


*ENDIF



Endproc

 
Can you debug and see in what method and in what line the error happens?
Is this really a system error message, is it really erroring when reaching MAX_USERS? Or does it happen after the server hass run a long time? I'd make a test starting this server fresh and make 10 or more requests for testing that.

MAX_USERS is a limiting factor here, there's no #DEFINE in the code you posted, so it's to be assumed, the SCX uses an include file, in which MAX_USERS is defined. Open the SCX and in the form menu pick the menu item "Include File...", see to which .h File it points and open that file. See how MAX_USERS is defined in there. Higher that, recompile.

I can't imagine 10 instances of the winsock would lead to insufficient memory, unless you would allocate huge amounts of memory for each user connecting. If the problem is only coming after a long uptime, you seem to have a memory leak. Watch SYS(1016) and see at which point the server crashes with insufficient memor error.

Bye, Olaf.
 
thanks olaf
i will do that.
and am i using winsock in a right way?
 
Olaf said:
I`D at least run a beatify on it to make the code reaable.

I agree.

Ariftheruvath, I'd also ask that, when you post code it the forum, you wrap in in [ignore]
Code:
 /
[/ignore] tags (or use the corresponding button on the toolbar) to make it more readable. And also that you remove the irrelevant code. We don't need to know the form's Top, Left, Height, etc, for example.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
hi Olaf
i checked with sys(1016).
the APP started with using 1.5 MB even after 10 clients connected.
but later ..after 24+ hours it shows 500 MB. there is a huge memory leak.
as i mentioned earlier i use 1+15 mswinsck.ocx
1 is listening to port 9999 and on connection request it handing over the request to any available socket
whose state<>7 (15 sockets already assigned to object array and state=listening)
my app is running in an SBS 2007.
what could be the issue :( ?
 
Memory Leaks are hard to find. But at least you can detect them. The easiest short term solution to the problem is restarting the whole exe from time to time.
To shut down without lossing connections you can implement a very simple notification from the current exe to the next instance running.
-Write out a wait.txt then start your exe as secondary instance.
-In start of the exe look for a wait.txt, if it exists, start up rmtlisten1 but wait before putting it into listen state. Write out a ready.txt instead
-In the first process having written out the wait.txt look for the ready.txt and if that exists shut down rmtlisten1 and delete wait.txt, let the rest of the current requests running, until all further winsocks are finished.
-The second process can put it's rmtlisten1 into listening state as soon as wait.txt is removed and then remove the ready.txt
-The first instance can finish, after all sockets have finished

You have seamlessly replaced one with another process and the exit of the first process will free it's resources.
It's not a bad plan to do this anyway, no matter how stable your process would be.

The memory leak can come from anywhere, rmtlisten1 or the other winsocks or vfps own caching or whatever else. You can change your ways and drop ready winsocks and replace them with new instances, that may solve the problem, if its not the main rmtlisten1 winsock having the leak.

It's easy to check for files in a do while not FILE(..) loop, just put DOEVENTS in the loop body:

Code:
...
Thisform.rmtlisten1.janal.Object.LocalPort = srvport
strtofile("","...<<put a reeasonable path in here>>...ready.txt")
do while file("...<<put a reeasonable path in here>>...wait.prg")
   doevents force
enddo
Thisform.rmtlisten1.janal.Object.Listen
erase ("...<<put a reeasonable path in here>>...ready.txt")

...

Code:
...
licarray(i).janal.ConnectionRequest(requestid)
If val(sys(1016))>250000000
   strtofile("","...<<put a reeasonable path in here>>...wait.txt")
   Run /n your.exe
   do while not file("...<<put a reeasonable path in here>>...ready.prg")
      doevents force
   enddo
   Thisform.rmtlisten1.janal.Object.Close
   erase ("...<<put a reeasonable path in here>>...wait.txt")
Endif
Exit
...

Then elsewhere wait, until all other sockets are back in ready state and quit the app to free memory.

Bye, Olaf.
 
From what I remember the design is only halfways right. You have one listener and accept a request in secondary worker sockets. But you create new ones and dispose them, when they're done instead of putting them back into available state and reuse them. So you may continue to have 15 slots for worker sockets, but create them when needed and release them, too, to free memory. Changing that may solve your memory problem. also DOEVENTS FORCE before each Exit and at the end of the proc and call SYS(1104) to free unused memory.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top