Question about winsock in ActiveX DLL

I am trying to add a date checker to an ActiveX DLL I am writing. I would like to get the date from a NTP server on the net. I found this class module code:

http://www.vbip.com/comment.asp?1303

(shown below) so that I can use winsock without a form in my DLL. How do I get started and get the time with winsock? With a form and control, I would just be able to:

Winsock1.RemoteHost = "pogostick.net"
Winsock1.RemotePort = 13
Winsock1.Connect

and

Dim strData As String
Winsock1.GetData strData, vbString
MsgBox strData
Winsock1.Close

in DataArrival per http://www.skillreactor.org/cgi-bin/index.pl?inettime

Any help for a winsock newbie (that is totally over his head) would be fantastic! Thanks.

'Winsock without form

' #VBIDEUtils#************************************************************
' * Programmer Name : Hector Sosa, Jr
' * E-Mail :
' * Date : 05/23/2001
' **********************************************************************
' * Comments : Winsock ocx without a form
' *
' * This class wraps the winsock.ocx methods and properties. This
' * allows you to use winsock functions without putting the ocx on
' * a form. This class can be compiled into a dll if wanted. It was
' * said on the usenet that it could not be done, but I did it. I
' * hope this saves people from headaches and upset stomachs ;-) Enjoy!
' *
' **********************************************************************

'------------------------------------------------------------------------
'
' Class Module clsWinsock
' File: clsWinsock.cls
' Author: Hector
' Date: 5/10/01
' Purpose: This class allows to use the winsock functions without having
' to put a winsock control on a form. Make sure to have a
' reference to the winsock.ocx in the project where you're going
' to use this class or this won't work.
'
'------------------------------------------------------------------------
Option Explicit
Private WithEvents objSocket As Winsock
Public Event DataInStream(ByVal lngSocketNumber As Long, ByVal strData As String)
Public Event SocketClosed(ByVal lngSocketNumber As Long)
Public Event ConnectionRequested(ByVal lngSocketNumber As Long)
Public Event AcceptedSocket(ByVal lngSocketNumber As Long)
Private mvarPortNumber As Long
Private mvarCurrDataStream As String
Private mvarCurrentID As Long
Private blnSoftReturn As Boolean
'*****************************************************************************************
'* Property: CurrentSocketID
'* Notes: Returns the current socket number.
'*****************************************************************************************
Public Property Get CurrentSocketID() As Long
    CurrentSocketID = mvarCurrentID
End Property

'*****************************************************************************************
'* Property: CurrDataStream
'* Notes: Returns the raw input from thecurrent socket.
'*****************************************************************************************
Private Property Let CurrDataStream(ByVal vData As String)
    mvarCurrDataStream = vData
End Property

Public Property Get CurrDataStream() As String
    CurrDataStream = mvarCurrDataStream
End Property

'*****************************************************************************************
'* Property: LocalPort
'* Notes: Returns/Sets the port where the socket will be listening on.
'*****************************************************************************************
Public Property Let LocalPort(ByVal vData As Long)
    mvarPortNumber = vData
    objSocket.LocalPort = vData
End Property

Public Property Get LocalPort() As Long
    LocalPort = mvarPortNumber
End Property

Private Sub Class_Initialize()
    Set objSocket = New Winsock
End Sub

Private Sub Class_Terminate()
    If objSocket.State <> sckClosed Then objSocket.Close
    Set objSocket = Nothing
End Sub

Private Sub objSocket_Connect()
    Winsock1.RemoteHost = "pogostick.net"
    Winsock1.RemotePort = 13
    Winsock1.Connect
End Sub

'-----------------------------------------------------------------------
'
' Procedure objSocket_ConnectionRequest
' Author: Hector
' Date: 5/16/01
' Purpose: Handles connection requests.
' Result:
' Input parameters: requestID
'
' Output parameters:
'
'------------------------------------------------------------------------
Private Sub objSocket_ConnectionRequest(ByVal requestID As Long)
    If objSocket.State <> sckClosed Then objSocket.Close
    mvarCurrentID = requestID
    RaiseEvent ConnectionRequested(requestID)
End Sub

'-----------------------------------------------------------------------
'
' Procedure objSocket_DataArrival
' Author: Hector
' Date: 5/16/01
' Purpose: Handles data arriving to the socket.
' Result:
' Input parameters: bytesTotal
'
' Output parameters:
'
' Last Modification:
' 5/22/01 - Finished the handling of broken packets (consecutive streams).
'------------------------------------------------------------------------
Private Sub objSocket_DataArrival(ByVal bytesTotal As Long)
    Dim strIncoming As String
    Static strInputBuffer As String
    Dim strOutBuffer As String
    Dim intPos As Integer
    objSocket.GetData strIncoming
    CurrDataStream = strIncoming
    mvarCurrentID = objSocket.SocketHandle
    ' Replace Carriage Returns/Line Feeds orjust Line Feeds with
    ' a Carriage Return for consistant handling.
    strIncoming = Replace$(strIncoming, vbCrLf, vbCr)
    strIncoming = Replace$(strIncoming, vbLf, vbCr)
    ' Check for Carriage Returns in the incoming stream, and mark
    ' the position where it's found, if any.
    intPos = InStr(1, strIncoming, vbCr)
    ' Make sure that the Carriage Return is not at the beginning of the stream.
    ' If the Carriage Return is at position 1 then it means that it belongs to the
    ' previous stream.
    If intPos > 1 Then
    ' Grab a string including the Carriage Return for processing.
    strOutBuffer = Left$(strIncoming, intPos)
    strOutBuffer = StripCRLF(strIncoming)
    RaiseEvent DataInStream(mvarCurrentID, strOutBuffer)
    ' Flush the buffers so that data won't get added to the next stream.
    strOutBuffer = ""
    strInputBuffer = ""
    Else
    ' Add to the input buffer if there is noCarriage Return.
    strInputBuffer = strInputBuffer & strIncoming
    End If
    ' The code below handles broken packets,meaning that all the data did not
    ' come in one stream.
    '******************************************************************************
    If Right$(strIncoming, 1) = vbCr Then 'check last character
    blnSoftReturn = True
    End If
    If blnSoftReturn = True Then
    If Left$(strIncoming, 1) = vbCr Then
    strOutBuffer = Mid$(strInputBuffer, 1)
    strOutBuffer = StripCRLF(strOutBuffer)
    RaiseEvent DataInStream(mvarCurrentID, strOutBuffer)
    ' Flush the buffers so that data won't get added to the next stream.
    strOutBuffer = ""
    strInputBuffer = ""
    End If
    blnSoftReturn = False
    End If
    '*******************************************************************************
End Sub

Private Sub objSocket_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
    ' Lame error handling. If you want something better go ahead and put it here. When there is
    ' and error, it usually means that the socked was disconnected.
    If objSocket.State <> sckClosed Then objSocket.Close
    MsgBox "Something happened to socket #" & CStr(Number)
End Sub

'-----------------------------------------------------------------------
'
' Procedure StripCRLF
' Author: Hector
' Date: 5/16/01
' Purpose: Removes carriage returns and line feeds from incoming data.
' Result:
' Input parameters: strData
'
' Output parameters:
'
'------------------------------------------------------------------------
Private Function StripCRLF(strData As String)
    Dim strHold As String
    strHold = Replace(strData, vbCr, "")
    strHold = Replace(strHold, vbLf, "")
    StripCRLF = strHold
End Function

'-----------------------------------------------------------------------
'
' Procedure SocketListen
' Author: Hector
' Date: 5/16/01
' Purpose: Allows the socket to listen to incoming transmitions.
' Result:
' Input parameters: None
'
' Output parameters:
'
'------------------------------------------------------------------------
Public Sub SocketListen()
    objSocket.Listen
End Sub

'-----------------------------------------------------------------------
'
' Procedure SocketClose
' Author: Hector
' Date: 5/16/01
' Purpose: Stops the socket from listening to any more requests or data
' arrivals.
' Result:
' Input parameters: None
'
' Output parameters:
'
'------------------------------------------------------------------------
Public Sub SocketClose()
    objSocket.Close
End Sub

'-----------------------------------------------------------------------
'
' Procedure AcceptRequest
' Author: Hector
' Date: 5/16/01
' Purpose: Accepts a request to connect.
' Result:
' Input parameters: lngSocketNumber
'
' Output parameters:
'
'------------------------------------------------------------------------
Public Sub AcceptRequest(ByVal lngSocketNumber As Long)
    objSocket.Accept lngSocketNumber
    RaiseEvent AcceptedSocket(lngSocketNumber)
End Sub

'-----------------------------------------------------------------------
'
' Procedure SendData
' Author: Hector
' Date: 5/17/01
' Purpose: Sends data to the user connected to this socket.
' Result:
' Input parameters: sDataToSend
'
' Output parameters:
'
'------------------------------------------------------------------------
Public Sub SendData(ByVal sDataToSend As String)
    objSocket.SendData sDataToSend
End Sub
SaeserAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

eclaCommented:
It seems the class doesn't expose any property to connect to a Winsock Server

Is this code part of the original class?

Private Sub objSocket_Connect()
    Winsock1.RemoteHost = "pogostick.net"
    Winsock1.RemotePort = 13
    Winsock1.Connect
End Sub



0
fantasy1001Commented:
Can you let us know what are you want to do exactly?
What do you mean by getting the time from ntp server?

~ fantasy ~
0
SaeserAuthor Commented:
Yes, I placed this in as part of the class. But I am not sure this is correct.

Private Sub objSocket_Connect()
    Winsock1.RemoteHost = "pogostick.net"
    Winsock1.RemotePort = 13
    Winsock1.Connect
End Sub

What I would like to do is the following. I have a DLL which I have written. I would like to offer "trialware" that uses a internet time server to verify the date each time the DLL is initialized. When the date from the server is past the expiry date, the DLL will not run. I can avoid the user setting back the system clock or other registry programming to mark when and if the particular machine's date was modified. The Winsock control (on a form) works well, but not with the DLL (as I understand it from several hours of research on the net). Hence, the code I posted which was to wrap the .ocx (avoiding the form) and deal directly with the connections. Thanks again for any assistance.

Saeser
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

eclaCommented:
OK, remove that code and put this instead

Public Sub Connect(Host as stirng, Port as long)
 objSocket.RemoteHost = Host
 objSocket.RemotePort = Port
 objSocket.Connect
End Sub

To use the class as a Winsock Server:

Dim WithEvents oClsSock as new clsWinsock

oclsSock.LocalPort = 13
oclsSock.SocketListen

To use the class as a Winsock Client:

Dim WithEvents oClsSock as new clsWinsock

oclsSock.Connect("pogostick.net", 13)


To Send Data:
oclsSock.SendData "this is data"

To Receive Data:

Public Sub oClsSock_DataInStream(ByVal lngSocketNumber As Long, ByVal strData As String)
 str = strData
End Sub




0
Asif_SaadatCommented:
u can use FORMS in activeX dll
u cannt see them but u can use there properties and controls on them
place a winsock on form and add referecne of winsock in ur activex class
0
AzraSoundCommented:
And in this instance, do as Asif suggests and use a form.  Using the winsock control in a class without a form creates all sorts of headaches when you go to distribute your application.  Simply add a form to your dll, add a Winsock control to that form, and declare a variable in your class to use:


Private m_frmWinsock As WinsockForm


Private Sub Class_Initialize()
    Set m_frmWinsock = New WinsockForm
    Load m_frmWinsock
End Sub

Private Sub Class_Terminate()
    Unload m_frmWinsock
    Set m_frmWinsock = Nothing
End Sub


Then at any time you can access your winsock control:

m_frmWinsock.Winsock1.RemoteHost = ...
etc.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SaeserAuthor Commented:
Okay, you've convinced me that I should use the form. In my class_execute I have the following code.

With m_frmClient.tcpClient
   
        .RemoteHost = "pogostick.net"
        .RemotePort = 13
        .Connect
        .GetData strData, vbString
        NetTime = FormatDateTime(strData)
        .Close
       
    End With

 However, I get a runtime error 40006 stating: Wrong protocol or connection state for the requested transaction or request at:

.GetData strData

should this always be performed in _dataarrival in the form? If so, how what is the best way to get the contents of strData to back to my class_execute?

Many thanks. The end is near. Saeser
0
AzraSoundCommented:
Best thing to do would be to, yes, use GetData in the DataArrival event and then notify the client that the data has been received through event notification.  However, if you need to get the data before returning control to the client, you might try something like:


.Connect

Do Until .BytesReceived > 0
    DoEvents
Loop

.GetData strData, vbString
0
SaeserAuthor Commented:
I figured out what I was doing wrong. I was calling:

With m_frmClient.tcpClient
   
        .RemoteHost = "pogostick.net"
        .RemotePort = 13
        .Connect
        .GetData strData, vbString
        NetTime = FormatDateTime(strData)
        .Close
       
End With

from within my class_execute instead of in the class_initialize. This screwed with status of the socket. I took your suggestion and placed:

        .GetData strData, vbString
        NetTime = FormatDateTime(strData)
        .Close

in my winsock control named "tcpClient" on the form "frmClient" in the _dataArrival subroutine. strData and the FormatDateTime function work perfectly. Final question, how do I get the value of NetTime back to the class_initialize function to compare to the time expiry in my program? I noted that tcpClient_dataArrival is private...

Many, many thanks for the help. I've learned a lot...Saeser
0
AzraSoundCommented:
Instead of using class_initialize, I would have a public sub in your DLL that you call after instantiating it, giving you more control, e.g.,

Dim o As New MyDLL
Dim dtNetTime As Date

dtNetTime = o.GetNetTime


The GetNetTime function would connect and get the information from your server.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.