Solved

Question about winsock in ActiveX DLL

Posted on 2003-11-06
10
1,715 Views
Last Modified: 2013-11-13
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
0
Comment
Question by:Saeser
  • 3
  • 3
  • 2
  • +2
10 Comments
 

Expert Comment

by:ecla
ID: 9698783
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
 
LVL 5

Expert Comment

by:fantasy1001
ID: 9698911
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
 

Author Comment

by:Saeser
ID: 9699015
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
 

Expert Comment

by:ecla
ID: 9699076
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
 
LVL 3

Assisted Solution

by:Asif_Saadat
Asif_Saadat earned 100 total points
ID: 9699184
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 28

Accepted Solution

by:
AzraSound earned 400 total points
ID: 9702404
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
 

Author Comment

by:Saeser
ID: 9703620
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
 
LVL 28

Expert Comment

by:AzraSound
ID: 9703682
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
 

Author Comment

by:Saeser
ID: 9704675
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
 
LVL 28

Expert Comment

by:AzraSound
ID: 9705985
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

746 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