Client/Server Sockets in V91B

emnu

Member
hi,

A view days agoo i was dooing some testing with 4GL sockets in V91B.

I've made a (quite) simple Client/Server program which does the following:

A promon-alike server program keeps track of the users which connect to the client Socket program. When a users connects, the user name and hour of connections is sent to the promon-alike server program.

+The system consists of the next steps:

server.w:
* Get ip address for server, and connect server to serviceport
* Listen for connection of clients who send their logon name
and hour of connection (polling procedure) or disconnection.
*Put client logon + connection time in a list on the server screen.

client.w:
* Get ip address of server
* Write connect string to server when STARTUP client
* Write disconnect string to server when SHUTDOWN client.

*** PROBLEM ***

Everything seems to work fine, the server starts up, the client connects and disconnects, but when there are more then 1 client connected to the server, the disconnect is mentioned in the server-list, but the rest of the disconnections don't fire any more, so only the first disconnect of the client is mentioned in the server list.
Have a clue ????

Thanx for any response,

Emmanuel Nuyttens
Senior Programmer at C&C computers NV
OUDENAARDE _ BELGIUM




+The Code:


***************
*** SERVER.W ***
***************

/* main */

MAIN-BLOCK:
DO ON ERROR UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:
RUN enable_UI.

ON 'tab':U OF fill-in-ip IN FRAME frame-ip
DO:
HIDE FRAME frame-ip.
ENABLE ALL WITH FRAME {&FRAME-NAME}.
END.

/* Get IP-adress of server */
cIP = ifunc_ip().
IF LENGTH(TRIM(cIp)) = 0 THEN
DO:
MESSAGE "IP address for server not found !"
SKIP "Please fill-in the IP-address" VIEW-AS ALERT-BOX.
VIEW FRAME frame-ip.
DISABLE ALL WITH FRAME {&FRAME-NAME}.
ENABLE ALL WITH FRAME frame-ip.
WAIT-FOR "tab":U OF fill-in-ip IN FRAME frame-ip.
ASSIGN
cIp = fill-in-ip:SCREEN-VALUE IN FRAME frame-ip.
END.
ASSIGN
fill-in-ip:SCREEN-VALUE IN FRAME {&FRAME-NAME} = "IP-
Adres : ":U + cIP + " ServicePoort : 3333":U.
cConnectString = "-H ":U + cIp + " -S 3333 -N tcp":U.
APPLY "choose":U TO button-start.
IF NOT THIS-PROCEDURE:pERSISTENT THEN
WAIT-FOR CLOSE OF THIS-PROCEDURE.
END.

/* Start the server - button-start */

DO:

/* Create Server Socket */
IF NOT VALID-HANDLE(hServerSocket) THEN
DO:
{&SELF-NAME}:LABEL = "&Stop Server".
CREATE SERVER-SOCKET hServerSocket.
fill-in-msg:SCREEN-VALUE IN FRAME {&FRAME-NAME}
= "Server STARTED".
/* Connection procedure */
hServerSocket:SET-CONNECT-PROCEDURE( "connProc":U).
aOk = hServerSocket:ENABLE-CONNECTIONS(cConnectString).
MESSAGE "Enabled connections:" aOk.
IF NOT aOk THEN
RETURN.
RUN adecomm/_statdsp.p (hstatus,1,"Waiting for
Connections ...").

END. ELSE
DO:
IF {&self-name}:LABEL = "&Stop Server" THEN
DO:
{&self-name}:LABEL = "&Start Server".
aOk = hServerSocket:DISABLE-CONNECTIONS().
MESSAGE "Disabled connections:" aOk.
IF NOT aOk THEN
RETURN.
ELSE
fill-in-msg:SCREEN-VALUE IN FRAME {&FRAME-NAME}
= "Server STOPPED".
RUN adecomm/_statdsp.p (hstatus,1,"Wait for connections
STOPPED...").
END. ELSE DO:
{&self-name}:LABEL = "&Stop Server".
aOk = hServerSocket:ENABLE-CONNECTIONS(cConnectString).
MESSAGE "Enabled connections:" aOk.
IF NOT aOk THEN
RETURN.
ELSE
fill-in-msg:SCREEN-VALUE IN FRAME {&FRAME-NAME}
= "Server STARTED".
RUN adecomm/_statdsp.p (hstatus,1,"Wait for connections
STARTED ...").
END.
END.

END.

/* Connection procedure */

/*------------------------------------------------------------------------------
Purpose: Get socket from connected client Client
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
/* Connection procedure for server socket */
DEFINE INPUT PARAMETER iphSocket AS HANDLE. /*Socket implicitly created*/

ASSIGN
hSocket = iphSocket.





END PROCEDURE.


/* Polling for Connected clients every 5 seconds
this procedure is executed by the OCX.tick Activex
distributed with Progress
*/

/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/
IF VALID-HANDLE(hSocket) THEN
DO:
IF hSocket:GET-BYTES-AVAILABLE() > 0 THEN
DO:
/* 64 bytes reserveren voor inkomende string */
SET-SIZE(mBuffer) = 64.
hSocket:READ (mBuffer,1,hSocket:GET-BYTES-AVAILABLE()).
cString = GET-STRING(mBuffer,1). /*Unmarshal data*/
BELL.
/* Put connected client in connection list */
SELECT-logon:ADD-LAST(cString) IN FRAME {&FRAME-NAME}.
END.
END.
END PROCEDURE.

**********
*CLIENT.W*
**********

/* Main */

MAIN-BLOCK:
DO ON ERROR UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:

ON 'tab':U OF fill-in-logon IN FRAME frame-logon
DO:
HIDE FRAME frame-logon.
RUN connProc.
RETURN.
END.

RUN enable_UI.
DISABLE ALL WITH FRAME {&FRAME-NAME}.
VIEW FRAME frame-logon.
/* Insert adress server if not same machine */
cIP = ifunc_ip().
IF LENGTH(TRIM(cIp)) = 0 THEN
DO:
MESSAGE "IP adres server not found !" VIEW-AS ALERT-BOX.
APPLY "close":U TO THIS-PROCEDURE.
END.
ASSIGN
fill-in-ip:SCREEN-VALUE IN FRAME frame-logon = cIP.

ENABLE ALL WITH FRAME frame-logon.

IF NOT THIS-PROCEDURE:pERSISTENT THEN
WAIT-FOR CLOSE OF THIS-PROCEDURE.
END.

/* Connection Procedure */

/*------------------------------------------------------------------------------
Purpose:
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/

/* Connect to service at server */
CREATE SOCKET hSocket.
hSocket:CONNECT (cConnectString).
IF hSocket:CONNECTED() THEN
DO:
ASSIGN
cTime = STRING(TIME,"hh:mm:ss") /* in var, voor zelfde tijd
doorsturen naar server */
fill-in-user:SCREEN-VALUE IN FRAME {&FRAME-NAME} = fill-in-
logon:SCREEN-VALUE IN FRAME frame-logon + " logged on
at " + cTime.

ENABLE ALL WITH FRAME {&FRAME-NAME}.
MESSAGE "Connected OK".
END.
ELSE DO:
MESSAGE "Could not connect".
APPLY "close":u TO THIS-PROCEDURE.
END.

RUN iproc_snd_msg(" logged on",cTime).


END PROCEDURE.

/* Shutdown client - on choose of close button */

RUN iproc_snd_msg(" logged off", STRING(TIME,"hh:mm:ss":U)).
hSocket:DISCONNECT().
APPLY "close":u TO THIS-PROCEDURE.


/* send connect message to server when STARTUP CLIENT */
/* send disconnect message to server when SHUTDOWN CLIENT */

/*------------------------------------------------------------------------------
Purpose: iproc_snd_msg
Parameters: <none>
Notes:
------------------------------------------------------------------------------*/

DEF INPUT PARAMETER ipcMsg AS CHAR NO-UNDO.
DEF INPUT PARAMETER ipcTime AS CHAR NO-UNDO.

SET-SIZE(mBuffer) = 64.
cString = fill-in-logon:SCREEN-VALUE IN FRAME frame-logon + " " + TRIM(ipcMsg) + " at " + ipcTime.

PUT-STRING(mBuffer,1) = cString.

hSocket:WRITE (mBuffer,1,LENGTH(cString)).

END PROCEDURE.



/* IFUNC_IP */

RETURNS CHARACTER
( /* parameter-definitions */ ) :
/*------------------------------------------------------------------------------
Purpose: Bepaal ip adres server
Notes:
------------------------------------------------------------------------------*/

DEF VAR cLijn AS CHAR NO-UNDO.
DEF VAR cIp AS CHAR NO-UNDO.
DEF VAR iIndex AS INT NO-UNDO.

OS-COMMAND SILENT md C:\TEMP.
OUTPUT TO "C:\TEMP\IPCONFIG.TXT":U.
OS-COMMAND SILENT ipconfig.
OUTPUT CLOSE.

INPUT FROM "C:\TEMP\IPCONFIG.TXT":U.

lus:
REPEAT:
IMPORT UNFORMATTED cLijn.
IF INDEX(cLijn,"IP Address":U) > 0 THEN
DO:
cIp = TRIM(cLijn).
LEAVE lus.
END.
END.
IF LENGTH(cIp) > 0 THEN
DO:
iIndex = INDEX(cIp,":":U).
IF iIndex > 0 THEN
cIp = SUBSTR(cIp,iIndex + 1 ,LENGTH(cIp) - iIndex).
END.

RETURN cIp. /* Function return value. */

END FUNCTION.
 
Top