Just learn Winsock API (1) - create a Visual Basic project template

xiaoxiao2021-03-06  201

In the first part of this series, we have to learn some basic Winsock API functions. These functions provide the necessary functions in the initialization of Winsock services, domain name resolution, exception handling. If you don't understand these functions, you can't complete some interesting things such as: establishing sockets, sending received data, etc. Here is the list of functions involved in this section:

WSAStartup WSACleanup gethostbyaddr gethostbyname gethostname getservbyname getprotobynumber getprotobyname getservbyport inet_addr inet_ntoa htons htonl ntohl ntohs order to test the function and use of these functions takes about a dozen sample programs, so I suggest that the best approach is to create a VB project template, which contains all of these API functions, custom functions, some forms and code are used to run the test sample program we will do. create project

All examples are standard EXE programs, so select menu file | new project, select the project in the new pop-up dialog box, and click OK. Rename the project to BasicWinsockApi. The default form is named frmmain. Select Menu Project | Add Module Create a code module that is used to include some declarations of API functions and some custom functions definitions. Return the code module to Modwinsock. Insert an API declaration to open the code of the Modwinsock module, insert the following code. Now we will not explain these statements, and there are detailed descriptions of these functions in future articles.

Option Explicit Public Const INADDR_NONE = & HFFFF Public Const SOCKET_ERROR = -1Public Const WSABASEERR = 10000Public Const WSAEFAULT = (WSABASEERR 14) Public Const WSAEINVAL = (WSABASEERR 22) Public Const WSAEINPROGRESS = (WSABASEERR 50) Public Const WSAENETDOWN = (WSABASEERR 50) Public Const WSASYSNOTREADY = (WSABASEERR 91) Public Const WSAVERNOTSUPPORTED = (WSABASEERR 92) Public Const WSANOTINITIALISED = (WSABASEERR 93) Public Const WSAHOST_NOT_FOUND = 11001Public Const WSADESCRIPTION_LEN = 257Public Const WSASYS_STATUS_LEN = 129Public Const WSATRY_AGAIN = 11002Public Const WSANO_RECOVERY = 11003Public const WSANO_DATA = 11004Public Type WSAData wVersion As Integer wHighVersion As Integer szDescription As String * WSADESCRIPTION_LEN szSystemStatus As String * WSASYS_STATUS_LEN iMaxSockets As Integer iMaxUdpDg As Integer lpVendorInfo As LongEnd TypePublic Type hOSTENT hName As Long hAliases As Long hAddrType As Integer h Length As Integer hAddrList As LongEnd TypePublic Type servent s_name As Long s_aliases As Long s_port As Integer s_proto As LongEnd TypePublic Type protoent p_name As String 'Official name of the protocol p_aliases As Long' Null-terminated array of alternate names p_proto As Long 'Protocol number , in host byte orderEnd TypePublic Declare Function WSAStartup _ Lib "ws2_32.dll" (ByVal wVR As Long, lpWSAD As WSAData) As LongPublic Declare Function WSACleanup Lib "ws2_32.dll" () As LongPublic Declare Function gethostbyaddr _ Lib "ws2_32.dll "

(Addr As Long, ByVal addr_len As Long, _ ByVal addr_type As Long) As LongPublic Declare Function gethostbyname _ Lib "ws2_32.dll" (ByVal host_name As String) As LongPublic Declare Function gethostname _ Lib "ws2_32.dll" (ByVal host_name As String, _ ByVal namelen As Long) As LongPublic Declare Function getservbyname _ Lib "ws2_32.dll" (ByVal serv_name As String, _ ByVal proto As String) As LongPublic Declare Function getprotobynumber _ Lib "ws2_32.dll" (ByVal proto As Long) As LongPublic Declare Function getprotobyname _ Lib "ws2_32.dll" (ByVal proto_name As String) As LongPublic Declare Function getservbyport _ Lib "ws2_32.dll" (ByVal port As Integer, ByVal proto As Long) As LongPublic Declare Function inet_addr _ Lib "ws2_32 .dll "(byval cp as string) As longpublic declare function inet_ntoa _ lib" ws2_32.dll "(byvalin") (byvalin ") _ lib" ws2_32.dll "(Byval Host short As Integer) As IntegerPublic Declare Function htonl _ Lib "ws2_32.dll" (ByVal hostlong As Long) As LongPublic Declare Function ntohl _ Lib "ws2_32.dll" (ByVal netlong As Long) As LongPublic Declare Function ntohs _ Lib "ws2_32. dll "(ByVal netshort As Integer) As IntegerPublic Declare Sub RtlMoveMemory _ Lib" kernel32 "(hpvDest As Any, _ ByVal hpvSource As Long, _ ByVal cbCopy As Long) Public Declare Function lstrcpy _ Lib" kernel32 "Alias" lstrcpyA "

(Byval LPString1 As String, _ BYVAL LPSTRING2 AS Long) AS Longpublic Declare Function Lstrlen _ lib "kernel32" Alias ​​"Lstrlena" (Byval LPSTRING AS ANY) AS Long Establish auxiliary function Winsock API extensively using C / C unsigned data type Such as: Unsigned Short, 2 bytes), unsigned long (unsigned long, 4 bytes). Visual Basic also has 2 or 4-bytes of integer data type Integer and long, but unfortunately they are symbolic, VB does not directly support unsigned data types. Language data type length range C / C u_short2 bytes0 to 65535c / c u_long4 bytes0 to 4294967295vbinteger2 bytes-32768 to 32767vblong4 BYTES-2147483648 To 2147483647

However, the parameters or returned values ​​received by the Winsock API are some bytes, and we can replace the data type of VB, but we need some subroutines to perform these values. Fortunately, we don't need to invent what algorithm, Microsoft's support team has solved this problem. Check out the Microsoft Knowledge Base

Howto: Convert Between Signed and UNSIGNed Numbers, we will use these functions, so insert the following code into the ModwInsock code module.

Private Const OFFSET_4 = 4294967296 # Private Const MAXINT_4 = 2147483647Private Const OFFSET_2 = 65536Private Const MAXINT_2 = 32767Public Function UnsignedToLong (Value As Double) As Long '' The function takes a Double containing a value in the 'range of an unsigned Long and returns a Long that you 'can pass to an API that requires an unsigned Long' If Value <0 Or Value> = OFFSET_4 Then Error 6 'Overflow' If Value <= MAXINT_4 Then UnsignedToLong = Value Else UnsignedToLong = Value - OFFSET_4 End If 'End FunctionPublic Function LongToUnsigned (Value As Long) As Double '' The function takes an unsigned Long from an API and 'converts it to a Double for display or arithmetic purposes' If Value <0 Then LongToUnsigned = Value OFFSET_4 Else LongToUnsigned = Value End If' End FunctionPublic function unsignedtointeger (Value As Long) AS Integer '' The Function Takes A Long Containing a value in the range 'of an unsigned Integer and returns an Integer that you' can pass to an API that requires an unsigned Integer 'If Value <0 Or Value> = OFFSET_2 Then Error 6' Overflow 'If Value <= MAXINT_2 Then UnsignedToInteger = Value Else UnsignedToInteger = Value - OFFSET_2 End If 'End FunctionPublic function IntegerToUnsigned (Value As Integer) As Long' 'The function takes an unsigned Integer from and API and' converts it to a Long for display or arithmetic purposes' If Value <

0 THEN INTEGERTOUNSIGNED = VALUE OFFSET_2 ELSE Integertounsigned = Value End If 'End Function The value returned by the API function is a pointer to the character, which does not directly store the String type variable in VB. Win32API provides us with a function lstrcpy let us point a pointer to another variable to another variable. Public Declare Function LSTRCPY LIB _ "Kernel32" Alias ​​"LSTRCPYA" (BYVAL LPSTRING2 AS STRING) AS long parameter lpstring2 is a pointer to the string, and the parameter lpstring1 is the buffer of the stored string. The buffer must have enough length to accommodate the string, so we must know the length of the string before calling the function. Another Win32API function lstrlen helped us complete this feature - get the length of the string pointed to by a pointer. Public Declare Function Lstrlen Lib "kernel32" Alias ​​"LSTRLENA" (Byval LPString as any) AS Long now, we can write a function StringFromPointer to get a string through a pointer. Insert the following code modWinsock Module: Public Function StringFromPointer (ByVal lPointer As Long) As String 'Dim strTemp As String Dim lRetVal As Long' 'prepare the strTemp buffer strTemp = String $ (lstrlen (ByVal lPointer), 0)' 'copy the string into the strTemp buffer lRetVal = lstrcpy (ByVal strTemp, ByVal lPointer) '' return a string If lRetVal Then StringFromPointer = strTemp 'End Function well, modWinsock module ready, we're going to modify this project default form. Modify the default form Open the design interface of the frmmain form, add two Button, change the attributes of the two buttons to the following table:

NamecaptionDefaultcancelcmdget & Gettrue Cmdexite & xit TRUE

Open the code design interface and add the following code to the Form_Load Event Process Process.

Private sub flow_load ()

'

Dim lngretval

As long

DIM STRERRORMSG

As string

Dim UdtwinsockData

AS

WSADATA

DIM LNGTYPE

As long

Dim lngprotocol

As long

'' Start Up Winsock Service

LNGRETVAL = WSASTARTUP (& H101, UDTWinsockData)

'

IF lngretval <> 0

THEN

'' SELECT CASE LNGRETVAL

Case WSASYSNOTREADY

STRERRORMSG = "The underlying network subsystem is not" & _

"Ready for Network Communication."

Case WsaverNotsupported

STRERRORMSG = "The Version of Windows Sockets API Support" & _

"Requester is not provided by this particular" & _

"Windows Sockets Implementation."

Case WSaeinval

STRERRORMSG = "The Windows Sockets Version Specified by The" & _

Application is not supported by this dll. "

End SELECT

'

Msgbox StrerrorMsg, Vbcritical

'

END IF

'

End Sub

Before our program calls any Winsock API function, we need to initialize the Winsock service. To this end we need to call the WSAStartup function during the form's Form_Load event handler. Because we use this function in any programs that use Winsock, we join this function to the project template, so you don't have to copy this function in the future.

Similarly, there are some work to do when the form is unloaded. In the form of the form_unload event handle, we call the WSACLEANUP function to tell the system no longer need to use the Winsock service, showerrorMSG is used to display the Winsock's Error Description dialog.

Private Sub Form_Unload (Cancel As Integer) Call WSACleanupEnd SubPrivate Sub ShowErrorMsg (lngError As Long) 'Dim strMessage As String' Select Case lngError Case WSANOTINITIALISED strMessage = "A successful WSAStartup call must occur" & _ "before using this function." Case WSAENETDOWN strMessage = "The network subsystem has failed." Case WSAHOST_NOT_FOUND strMessage = "Authoritative answer host not found." Case WSATRY_AGAIN strMessage = "Nonauthoritative host not found, or server failure." Case WSANO_RECOVERY strMessage = "A nonrecoverable error occurred." Case WSANO_DATA strMessage = "Valid name, no data record of requested type." Case WSAEINPROGRESS strMessage = "A blocking Windows Sockets 1.1 call is in" & _ "progress, or the service provider is still" & _ "processing a callback function. "Case WSAEFAULT strMessage =" The name parameter is not a valid part of "& _" the user address space. "Case WSAEINTR strMessage =" A blocking Windows Socket 1.1 call was "& _" canceled through WSACancelBlockingCall. "End SELECT 'MSGBOX STRMESSAGE, VBEXCLAMATION' End Sub, there is another forgetting, plus:

Private subdexit_click () unload mend Sub

转载请注明原文地址:https://www.9cbs.com/read-128184.html

New Post(0)