So here's a fun little trick you can do quite easily with REALbasic. Let's say you're on Windows (because all good people run Windows, remember. ;-)) and you want to send a file to another machine (Windows or not). Well, it's trivial to write some REALbasic code which opens up the file, starts sending it out, and so forth. However, in order to make that file transfer quickly, you still have to remember some things. For instance, don't read the entire file in at once since that could chew up RAM for very large files.
What if you don't want to worry about any of that jazz? Well, there's a neat WinSock API called TransmitFile which does this for you. It's also trivial to use in newer versions of REALbasic.
The API, when converted into an RB declare, looks like this:
Soft Declare Sub TransmitFile Lib "mswsock" ( socket as Integer, file as Integer, _
bytesToWrite as Integer, bytesPerSend as Integer, _
overlapped as Integer, transmitBuffers as Integer, flags as Integer )
You'll notice that we're soft declaring it. That's because this API doesn't exist on older OSes, like Windows 98 or ME (it's an NT only thing).
The tricky parts to this API have traditionally been the socket and file parameters. In earlier versions of REALbasic, there was no way to get a handle for a socket or a file. However, in more recent versions, you can grab these easily enough. That makes our calling code very neat:
if System.IsFunctionAvailable( "TransmitFile", "mswsock" ) then
Const TF_WRITE_BEHIND = &h4
Const TF_USE_SYSTEM_THREAD = &h10
Const TF_DISCONNECT = &h1
TransmitFile( TCPSocket1.Handle, _
mFile.Handle( BinaryStream.HandleTypeWin32Handle ), 0, 0, 0, 0, _
TF_DISCONNECT + TF_WRITE_BEHIND + TF_USE_SYSTEM_THREAD )
end if
You can get the socket handle using the .Handle property on SocketCore, and you can get the file handle by using the .Handle property on a stream object (I'm using a BinaryStream). Note that for file handles, you have to specify what type of handle you'd like. I'm saying that I want a Win32 HANDLE object. The remainder of the parameters are pretty easy if you read the documentation on MSDN.
The only thing to note is that because I am using a write behind buffer (asynchronous file transfer), the file handle has to remain valid until the file is done sending. So that means you can't use a local variable to hold the BinaryStream. I put the stream object into a class property, and then in the Error event of the socket, I close the stream handle. This works because I have the socket closed when the transfer is done.
So there you have it, a one-line call to transmit a file efficiently on Windows. Easy as pie!
Makes one wonder what they are if you run Windows XP SP 2, Linux (4 versions) and OS X (2 versions).
Something like going to hell but doing it in style ? :)
Interesting API call though
What if you run OS X, Linux, Windows XP, and system 7 at one time, on one computer?
Namely XP base, PearPC, cygwinx, and basilisk ][.
nice aaron
@norman: 4 versions of linux? theres 1 version of linux...
-clay
4 distros using 2 different releases of the kernel
Ubuntu, Suse, Fedora and Gentoo
Might as well be 4 different versions
lol
it was just a pun at the confusion between "linux" and the stuff sitting on top
sorry, the sass gets the best of me
-clay