Update: I did not parse the string last night, I was wiped out from work. What I did do today is to start a project to provide some code that is not tied to my own system too much. It has been correctly pointed out that networking has to be fitted into the application at hand. "Team jinzai" is well aware of that, and I have started a project that can be made into a nice network utility while not violating my ISP agreement.
The snippet that follows will initialize WinInet and get a html page from my free Geocities account. That account is typical of free accounts in that they encase your HTML in a Javascript page, so it will contain alot of ads, icons, etc. Also, it does not get sent out like a straight HTML page, and the server is not guaranteed to provide any extra information about it. I have modified the code that has been used in the past for this purpose. The receive routine is not exactly robust. Basically, I give it a 32K buffer, and hope for the best. Ultimately, that is not acceptable because it either wastes memory or will fail to receive the file in its entirety. That requires more involved and specific stuff. You might not want that, so...feel free to modify it to suit your needs.
REM Project: wiseclient
REM Created: 6/7/2007 10:49:55 AM
REM
REM ***** Main Source File *****
REM
#constant NO_ERROR = 0
#constant ERROR_NOT_SUPPORTED = 50
#constant ERROR_INVALID_PARAMETER = 87
#constant ERROR_INSUFFICIENT_BUFFER = 122
#constant MESSAGE_ID_NAME = 0
#constant MESSAGE_ID_STRING = 0
#constant MESSAGE_ID_LOGONPWD = 251
#constant MESSAGE_ID_LOGONNAME = 252
#constant MESSAGE_ID_IFF = 253
#constant MESSAGE_NACK = 254
#constant MESSAGE_ACK = 255
#constant INTERNET_OPEN_TYPE_PRECONFIG = 0
#constant INTERNET_OPEN_TYPE_DIRECT = 1
#constant INTERNET_OPEN_TYPE_PROXY = 3
#constant INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4
#constant INTERNET_FLAG_ASYNC = 0x10000000
#constant INTERNET_FLAG_FROM_CACHE = 0x01000000
#constant INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE
#constant INTERNET_INVALID_PORT_NUMBER = 0
#constant INTERNET_DEFAULT_FTP_PORT = 21
#constant INTERNET_DEFAULT_GOPHER_PORT = 70
#constant INTERNET_DEFAULT_HTTP_PORT = 80
#constant INTERNET_DEFAULT_HTTPS_PORT = 443
#constant INTERNET_DEFAULT_SOCKS_PORT = 1080
#constant INTERNET_SERVICE_FTP = 1
#constant INTERNET_SERVICE_GOPHER = 2
#constant INTERNET_SERVICE_HTTP = 3
#constant HTTP_QUERY_CONTENT_LENGTH = 5
#constant HTTP_QUERY_FLAG_NUMBER = 0x20000000
#constant FLAG_ICC_FORCE_CONNECTION = 0x00000001
type IPADDRROW
dwAddr as dword
dwIndex as dword
dwMask as dword
dwBCastAddr as dword
dwReasmSize as dword
unused1 as word
unused2 as word
endtype
dim ipaddress() as IPADDRROW
global i as integer
global wininet as integer = 0
global hInternet as dword = 0x00000000
global hHTTPRequest as dword = 0x00000000
global hHTTPSession as dword = 0x00000000
global memory as integer = 0
global ptr as dword = 0x00000000
global result as integer = 0
global appname as string
global clientname as string
global remoteserver as string
appname = appname$()
clientname = "Wise Client"
sync off
autocam off
set text transparent
set text font "terminal"
set text size 14
set text to bold
InitializeWinInet()
remoteserver = HTTPGetRemoteServerAddress("geocities.com", ...
"/mtb61275/dbpro/test.htm")
GetIPAddressTable()
print clientname
print remoteserver
do
rem
loop
dwreturn = call dll(wininet, "InternetCloseHandle", hInternet)
delete dll wininet
if memory > 0
if memblock exist(memory)
delete memblock memory
endif
endif
end
function GetIPAddressString(address as integer)
local buildstr as string
buildstr = str$(address) + " is an invalid IP Address Table entry."
if address > -1 and address <= array count(ipaddress())
buildstr = str$(ipaddress(address).dwAddr && 0x000000ff) + "." + ...
str$((ipaddress(address).dwAddr && 0x0000ff00) >> 8) + "." + ...
str$((ipaddress(address).dwAddr && 0x00ff0000) >> 16) + "." + ...
str$((ipaddress(address).dwAddr && 0xff000000) >> 24)
endif
endfunction buildstr
function GetIPAddressTable()
local tempdll as integer = 1
local dwdllreturn as dword = 0x00000000
local sort as boolean = 0
local nomakememoryblk as integer = 1
local tempblk as integer = 2
local ptr as dword = 0x00000000
local ptrsize as dword = 0x0000
local numaddresses as integer = 0
local i as integer = 0
while dll exist(tempdll) and tempdll < 255
inc tempdll
endwhile
if tempdll > 255
exitfunction
endif
while memblock exist(nomakememoryblk) and nomakememoryblk < 32768
inc nomakememoryblk
endwhile
if nomakememoryblk > 32767
exitfunction
endif
tempblk = nomakememoryblk + 1
while memblock exist(tempblk) and tempblk < 32768
inc tempblk
endwhile
if tempblk > 32768
exitfunction
endif
load dll "iphlpapi.dll", tempdll
empty array ipaddress()
make memblock nomakememoryblk, 4
ptrsize = get memblock ptr(nomakememoryblk)
*ptrsize = 0
dwdllreturn = call dll(tempdll, "GetIpAddrTable", 0x00000000, ptrsize, sort)
make memblock tempblk, *ptrsize
ptr = get memblock ptr(tempblk)
fill memory ptr, 0x00, *ptrsize
dwdllreturn = call dll(tempdll, "GetIpAddrTable", ptr, ptrsize, sort)
if dwdllreturn = NO_ERROR
numaddresses = *ptr
inc ptr, 4
for i = 0 to numaddresses - 1
array insert at bottom ipaddress()
ipaddress().dwAddr = *ptr
inc ptr, 4
ipaddress().dwIndex = *ptr
inc ptr, 4
ipaddress().dwMask = *ptr
inc ptr, 4
ipaddress().dwBCastAddr = *ptr
inc ptr, 4
ipaddress().dwReasmSize = *ptr
inc ptr, 4
ipaddress().unused1 = *ptr
inc ptr, 2
ipaddress().unused2 = *ptr
inc ptr, 2
next i
endif
delete dll tempdll
delete memblock tempblk
delete memblock nomakememoryblk
endfunction
function HTTPGetRemoteServerAddress(host as string, document as string)
local buildstr as string
local dwreturn as dword = 0x00000000
local ptrbytesread as dword = 0x00000000
local buffer as dword = 0x00000000
buildstr = "Unable to connect to " + host
if hInternet <> 0
hHTTPSession = call dll(wininet, "InternetConnectA", hInternet, ...
host, INTERNET_DEFAULT_HTTP_PORT, 0x00000000, ...
0x00000000, INTERNET_SERVICE_HTTP, 0x00000000, ...
0x00000000)
if hHTTPSession = 0
rem error
else
hHTTPRequest = call dll(wininet, "HttpOpenRequestA", hHTTPSession, ...
0x00000000, document, 0x00000000, 0x00000000, ...
0x00000000, 0x00000000, 0x00000000)
if hHTTPRequest = 0
rem error
else
dwreturn = call dll(wininet, "HttpSendRequestA", hHTTPRequest, ...
0x00000000, 0x00000000, 0x00000000, ...
0x00000000)
if dwreturn <> 1
rem error
else
ptrbytesread = make memory(4)
fill memory ptrbytesread, 0x00, 4
buffer = get memblock ptr(memory)
dwreturn = call dll(wininet, "InternetReadFile", ...
hHTTPRequest, buffer, 2048, ptrbytesread)
inc buffer, *ptrbytesread
dwreturn = *ptrbytesread
while dwreturn <> 0
dwreturn = call dll(wininet, "InternetReadFile", ...
hHTTPRequest, buffer, 2048, ptrbytesread)
inc buffer, *ptrbytesread
dwreturn = *ptrbytesread
endwhile
buildstr = jzMakeDBString(memory)
delete memory ptrbytesread
endif
dwreturn = call dll(wininet, "InternetCloseHandle", hHTTPRequest)
endif
dwreturn = call dll(wininet, "InternetCloseHandle", hHTTPSession)
endif
endif
endfunction buildstr
function InitializeWinInet()
local dwreturn as dword
wininet = jzGetNextAvailableDLLID(0, 1)
load dll "wininet.dll", wininet
dwreturn = call dll(wininet, "InternetAttemptConnect", 0x00000000)
if dwreturn <> 0
hInternet = 0x00000000
else
hInternet = call dll(wininet, "InternetOpenA", appname, ...
INTERNET_OPEN_TYPE_PRECONFIG, 0x00000000, 0x00000000, ...
0x00000000)
memory = jzGetNextAvailableMemblockID(1)
make memblock memory, 32768
ptr = get memblock ptr(memory)
endif
endfunction
function jzGetNextAvailableDLLID(bDown as boolean, seed as integer)
local temp = seed
if seed < 1 or seed > 255 then exitfunction -1
do
if dll exist(temp) = 0 then exitfunction temp
if bDown = 1
dec temp
else
inc temp
endif
if temp < 1 or temp > 255 then exitfunction -1
loop
endfunction -1
function jzGetNextAvailableMemblockID(seed as integer)
local temp = seed
if seed < 1 then exitfunction -1
do
if memblock exist(temp) = 0 then exitfunction temp
inc temp
if temp < 0 then exitfunction -1
loop
endfunction -1
function jzMakeDBString(cstring_blockID as integer)
local ivalue as integer
local icount as integer
local offset as integer
local buildstr as string
offset = 0
icount = 0
buildstr = ""
ivalue = memblock byte(cstring_blockID, offset)
while ivalue > 0
buildstr = buildstr + chr$(ivalue)
inc offset
inc icount
if icount > 32767 then exitfunction buildstr
ivalue = memblock byte(cstring_blockID, offset)
endwhile
endfunction buildstr
I had originally intended to use the more capable WinHTTP API, but I discovered a big problem with that. Alot of developers have lost the include file for it because of how MS updates their stuff. I was able to load the dll fine, but when I went to get all of the pertinent info to use it, I could not find it anywhere. A quick search showed me page after page of people trying to find it. I downloaded the latest Windows Server 2003 SDK update, and got it from there. It is a little hard to find! Anyway, I will also code up a DBPro interface for that one. WinInet is very good, it also does gopher and ftp, it does not do IPV6, however. (But IPV6 is not as universally applied as it was supposed to be anyway.)
This will ultimately be serverless, but that is not to say that it is peer to peer. The server will be distributed; we are not going to violate the ISP agreement as I understand it, and we will be playing games across continents.