Code: Select all
' Minimal TCP/HTTP client
' By Brent D. Thorn, 10/2010
' A minimalistic TCP client which just happens to send the right string of
' bytes to get an HTTP server to respond. In this example, an IP discovery tool
' returns your IP.
' PUBLIC DOMAIN
PRINT "MINIMAL TCP HTTP CLIENT"
host$ = "www.b6sw.com"
port = 80
path$ = "/test/my-ip.shtml"
crlf$ = Chr$(13)+Chr$(10) ' Carriage return + line feed
request$ = _ ' Bytes sent to host server
"GET "+path$+" HTTP/1.1"+crlf$+_
"Host: "+host$+crlf$+_
"User-Agent: Minimal client"+crlf$+_
"Content-Length: 0"+crlf$+_
crlf$
response$ = Space$(64) ' Buffer size - may be increased
global paddrinfo
Open "ws2_32" For DLL As #wsock
Call WinsockInit
' Start up Winsock
e = WSAStartup(MAKEWORD(2, 2))
If e <> 0 Then e$ = "WSAStartup" : GoTo [CloseWS]
' Resolve host name to its IP
e = ResolveIP(host$, port)
If e <> 0 Then e$ = "ResolveIP" : GoTo [CloseWS]
' Create a TCP socket
sock = socket(2, 1, 6) ' AF_INET = 2, SOCK_STREAM = 1, IPPROTO_TCP = 6
If sock = -1 Then e$ = "socket" : e = WSAGetLastError() : GoTo [Cleanup]
' Connect to host server
r = connect(sock)
If r = -1 Then e$ = "connect" : e = WSAGetLastError() : GoTo [CloseSock]
' Send request string
r = send(sock, request$, Len(request$), 0)
If r > 0 _
Then Print r;" bytes sent" _
Else e$ = "send" : e = WSAGetLastError() : GoTo [CloseSock]
' Flush output buffer
r = shutdown(sock, 1) ' SD_SEND = 1
If r = -1 Then e$ = "shutdown" : e = WSAGetLastError() : GoTo [CloseSock]
' Read in response
Do
r = recv(sock, response$, Len(response$), 0)
Select Case
Case r > 0 : Print "Response> "; Left$(response$, r)
Case r = 0 : Print "Connection closed"
Case Else : e$ = "recv" : e = WSAGetLastError()
End Select
Loop While r > 0
[CloseSock] ' Close socket
r = closesocket(sock)
[Cleanup]
Call WSACleanup
[CloseWS] ' Display any error message, close DLL
If e <> 0 Then Print "Winsock error ";e;" in call to ";e$;"."
Close #wsock
End
Sub WinsockInit
' Initializes structs used in Winsock calls.
Struct addrinfo, _
aiflags As Long, _
aifamily As Long, _
aisocktype As Long, _
aiprotocol As Long, _
aiaddrlen As Long, _
aicanonname As Ptr, _
aiaddr As ULong, _
ainext As ULong
Struct sockaddr, _
sinfamily As Short, _
sinport As UShort, _
sinaddr As ULong, _
sinzero As Char[8]
Struct WSAData, _
wVersion As Word, _
wHighVersion As Word, _
szDescription As Char[257], _
szSystemStatus As Char[129], _
iMaxSockets As Word, _
iMaxUdpDg As Word, _
lpVendorInfo As Long
End Sub
Function WSAStartup( wVersionRequested )
CallDLL #wsock, "WSAStartup", _
wVersionRequested As Word, _
WSAData As Struct, _
WSAStartup As Long
End Function
Function ResolveIP( Host$, port )
' Host can be IP or name. Does a DNS lookup on latter and gets the first IP.
' Fills structs addrinfo and sockinfo for use later.
addrinfo.aifamily.struct = 2 'AF_INET
addrinfo.aisocktype.struct = 1 'SOCK_STREAM
addrinfo.aiprotocol.struct = 6 'IPPROTO_TCP
Struct local1, paddrinfo As ULong
CallDLL #wsock, "getaddrinfo", _
Host$ As Ptr, _
_NULL As Long, _
_NULL As Long, _
local1 As Struct, _
ResolveIP As Long
If ResolveIP <> 0 Then Exit Function
paddrinfo = local1.paddrinfo.struct
addrinfo.struct = paddrinfo
sockaddr.struct = addrinfo.aiaddr.struct
sockaddr.sinport.struct = htons(port)
End Function
Function htons( hostshort )
CallDLL #wsock, "htons", _
hostshort As Word, _
htons As Word
End Function
Function socket( af, type, protocol )
CallDLL #wsock, "socket", _
af As Long, _
type As Long, _
protocol As Long, _
socket As Long
End Function
Function connect( s )
namelen = Len(sockaddr.struct)
CallDLL #wsock, "connect", _
s As Long, _
sockaddr As Struct, _
namelen As Long, _
connect As Long
End Function
Function closesocket( s )
CallDLL #wsock, "closesocket", _
s As Long, _
closesocket As Long
End Function
Sub WSACleanup
' Free memory allocated by getaddrinfo
CallDLL #wsock, "freeaddrinfo", _
paddrinfo As ULong, _
r As Void
CallDLL #wsock, "WSACleanup", _
r As Void
End Sub
Function recv( s, ByRef buf$, buflen, flags )
CallDLL #wsock, "recv", _
s As Long, _
buf$ As Ptr, _
buflen As Long, _
flags As Long, _
recv As Long
End Function
Function send( s, buf$, buflen, flags )
CallDLL #wsock, "send", _
s As Long, _
buf$ As Ptr, _
buflen As Long, _
flags As Long, _
send As Long
End Function
Function shutdown( s, how )
CallDLL #wsock, "shutdown", _
s As Long, _
how As Long, _
shutdown As Long
End Function
Function WSAGetLastError()
CallDLL #wsock, "WSAGetLastError", _
WSAGetLastError As Long
End Function
Function MAKEWORD( b1, b2 )
MAKEWORD = b1 Or (256 * b2)
End Function