Image Map Image Map
Page 1 of 4 1234 LastLast
Results 1 to 10 of 34

Thread: new FAST DOS VNC-like remote control server

  1. #1

    Default new FAST DOS VNC-like remote control server

    thought there would be some pretty good interest in this, i see the topic mentioned somewhat often.

    firstly, i've been writing my own TCP/IP stack for DOS (MiniTCP) in 100% assembly. i wanted to try writing one that's a TSR, and to try and keep it as small/fast as possible. it doesn't actually do TCP yet, but it does perfectly handle the ARP, IP, and UDP layers (and it does properly forward packets for outside the local subnet out through a gateway) plus responds to ICMP pings. to test out the UDP code thoroughly, i thought it'd be cool to write a new VNC-like remote control app for DOS. it's MUCH faster than Tiny and telnetd. not only the network stack, but also the actual remote control server is in assembly as well.

    so far, MiniTCP itself uses only 18 KB total memory as a TSR (including buffers) at this point, but it will definitely increase a bit once i add the TCP layer. the remote control app takes an additional 5 KB of RAM as TSR, so you're looking at a total of only 23 KB RAM usage for the whole setup here.

    when the remote control is running, i only see about a 30-40% slowdown on my IBM 5150. it could use significantly less CPU if i were to have it check less lines on the screen for updates per clock tick. screenshot of the cheap little test client i wrote in VB6 (because it was fast to throw together just to see if the server worked)



    ^that's connected to the 5150 running the server.

    the VB6 client is pretty slow (gotta love PSET) but tomorrow i was going to redo it proper in C, and plan to upload everything for everybody to try out then.

    for some raw UDP performance numbers, my 12 MHz 286 with an NE2000-compatible NIC receives at 560 KB/s.

    EDIT: as i posted later on, you can download it now:
    server for DOS:
    http://rubbermallet.org/remoter-server.zip

    client for windows:
    http://rubbermallet.org/remoter-client.zip


    the IP stack doesn't do DHCP yet, so before you run minitcp.com you'll need to run setip.exe which will let you modify the IP, subnet mask, and gateway IP it will use. run minitcp.com first, then remoter.com

    for the client, once the server is running on a DOS machine just run remoter.exe with the IP address of the server on the command line. oh, and just a note... it only supports 80x25 text mode so far, and it wont work with an MDA.
    Last edited by Mike Chambers; August 7th, 2011 at 05:34 PM.
    My emulators!
    Fake86 8086/V20 PC emulator: http://sourceforge.net/p/fake86
    MoarNES Nintendo emulator: http://sourceforge.net/p/moarnes


  2. #2
    Join Date
    Mar 2011
    Location
    Norway/Japan
    Posts
    923

    Default

    This is super interesting. Not just the TCP aspect, but a VNC for DOS. Who would have thought it. I could have used something like that back in the day.. I did some other remote-control stuff back then, but the idea of VNC wasn't in the mindset back in the eighties.

    -Tor

  3. #3

    Default

    I'm sure it runs much faster than your QuickBASIC VNC client

  4. #4

    Default

    Please, not another TCP/IP stack starting with an 'm' ;-0

    You've had great progress since you've started on this.

    I am guessing that at 18KB that you have room for 10 incoming packets and the rest is code. (This is assuming maximum Ethernet MTU of 1514.) It does not have to get a lot larger with TCP added - uTCP (Contiki/Adam Dunkels) remains quite small. What you trade off in space affects performance though - you can't get a reasonable sized TCP/IP sliding window without more memory, and that is needed for both sending and receiving. The ability to resend packets automatically, handle multiple concurrent sockets, and the ability to accept incoming sockets adds a lot of code too. And then there is the entire IP fragment function, which is often not needed but is required for completeness.

    A 30 to 40% slowdown seems pretty harsh to handle. Instead of scanning the video buffer for updates I would just let the client send a UDP packet saying 'I need a refresh'. Upon receipt of that packet you send the contents of the screen back to the client. The lag time is slightly longer (the time it takes to send the first UDP packet), but you get rid of the background scanning. I'd gladly trade a millisecond or two of lag time for getting back to reasonable performance levels. Then you let the client decide how often to refresh the screen - if they need real-time updates then the machine will be slow, and if they don't the machine will be nearly full speed.

    I don't think I have tested my UDP numbers since 2006 when I first got it running. My UDP implementation is designed for low bandwidth DNS processing. Back when I did use it for file transfers I was getting a few hundred KB per second on a 386-40, but the timer management code and the checksumming routing have improved quite a bit since 2006. A large part of the time was spent doing the file reading/writing, so it's not directly comparable.

    The real speed measurement to shoot for is FTP over TCP/IP, with file I/O. That is what people do - they transfer files. I await your results ..


    Mike

  5. #5

    Default

    I'd consider making two versions -- one that only traps BIOS calls, and one that checks the video RAM. A good deal of software only relies on the BIOS video routines (or can be set to not write directly), so for those programs don't waste time with scanning video memory and only send data when the program sends data.

    Hell, my old alloy slave network ran that way... the dumb serial terminals only working with text-mode software that called BIOS... that was a fun setup -- five 8088's "on a card" sharing the host AT machine's hard drive, with serial as their only video and input.
    From time to time the accessibility of a website must be refreshed with the blood of owners and designers. It is its natural manure.
    CUTCODEDOWN.COM

  6. #6

    Default

    Quote Originally Posted by mbbrutman View Post
    Please, not another TCP/IP stack starting with an 'm' ;-0

    You've had great progress since you've started on this.

    I am guessing that at 18KB that you have room for 10 incoming packets and the rest is code. (This is assuming maximum Ethernet MTU of 1514.) It does not have to get a lot larger with TCP added - uTCP (Contiki/Adam Dunkels) remains quite small. What you trade off in space affects performance though - you can't get a reasonable sized TCP/IP sliding window without more memory, and that is needed for both sending and receiving. The ability to resend packets automatically, handle multiple concurrent sockets, and the ability to accept incoming sockets adds a lot of code too. And then there is the entire IP fragment function, which is often not needed but is required for completeness.

    A 30 to 40% slowdown seems pretty harsh to handle. Instead of scanning the video buffer for updates I would just let the client send a UDP packet saying 'I need a refresh'. Upon receipt of that packet you send the contents of the screen back to the client. The lag time is slightly longer (the time it takes to send the first UDP packet), but you get rid of the background scanning. I'd gladly trade a millisecond or two of lag time for getting back to reasonable performance levels. Then you let the client decide how often to refresh the screen - if they need real-time updates then the machine will be slow, and if they don't the machine will be nearly full speed.

    I don't think I have tested my UDP numbers since 2006 when I first got it running. My UDP implementation is designed for low bandwidth DNS processing. Back when I did use it for file transfers I was getting a few hundred KB per second on a 386-40, but the timer management code and the checksumming routing have improved quite a bit since 2006. A large part of the time was spent doing the file reading/writing, so it's not directly comparable.

    The real speed measurement to shoot for is FTP over TCP/IP, with file I/O. That is what people do - they transfer files. I await your results ..


    Mike
    heh, i'll try to think of a different name. for the buffers, there are actually 2 for incoming raw packets, 1 for IP receive, and 1 for IP send. i can just do away with multiple raw buffers i think, thats how i set it up when i first starting writing this but when a packet comes in, i'm just keeping interrupts disabled until all the processing on it is finished. i also reserved something like 4 KB for the stack which is MAJOR overkill so yeah i definitely can trim some fat off of it. and yes, raw UDP performance numbers aren't all that important. it's just a good way to measure the stack's performance without extra overhead.

    the bit about letting clients determine how often to update the screen is not a bad idea, but for now i think i'm just going to drop how many lines it checks per clock tick from 10 to 5 and see how it runs for now. i plan to start working on TCP tonight btw.
    My emulators!
    Fake86 8086/V20 PC emulator: http://sourceforge.net/p/fake86
    MoarNES Nintendo emulator: http://sourceforge.net/p/moarnes


  7. #7

    Default

    Quote Originally Posted by deathshadow View Post
    I'd consider making two versions -- one that only traps BIOS calls, and one that checks the video RAM. A good deal of software only relies on the BIOS video routines (or can be set to not write directly), so for those programs don't waste time with scanning video memory and only send data when the program sends data.

    Hell, my old alloy slave network ran that way... the dumb serial terminals only working with text-mode software that called BIOS... that was a fun setup -- five 8088's "on a card" sharing the host AT machine's hard drive, with serial as their only video and input.
    this is something i was considering already. what i probably will do is a hybrid of both methods.. drop the amount of lines it checks per tick in half, plus also do immediate updates on whatever line the cursor is on whenever there is a function 0Eh call to int 10h.
    My emulators!
    Fake86 8086/V20 PC emulator: http://sourceforge.net/p/fake86
    MoarNES Nintendo emulator: http://sourceforge.net/p/moarnes


  8. #8

    Default

    Quote Originally Posted by Mike Chambers View Post
    heh, i'll try to think of a different name. for the buffers, there are actually 2 for incoming raw packets, 1 for IP receive, and 1 for IP send. i can just do away with multiple raw buffers i think, thats how i set it up when i first starting writing this but when a packet comes in, i'm just keeping interrupts disabled until all the processing on it is finished. i also reserved something like 4 KB for the stack which is MAJOR overkill so yeah i definitely can trim some fat off of it. and yes, raw UDP performance numbers aren't all that important. it's just a good way to measure the stack's performance without extra overhead.

    the bit about letting clients determine how often to update the screen is not a bad idea, but for now i think i'm just going to drop how many lines it checks per clock tick from 10 to 5 and see how it runs for now. i plan to start working on TCP tonight btw.
    You can name it whatever you like - don't change the name on the account of me. But having two guys named Mike both do new TCP/IP stacks for old PCs and then having them both start with an 'm' is going to lead to confusion, guaranteed. ;-0

    With just two buffers you have more code there than I would have thought. I wouldn't disable interrupts while a packet is being processed; disabling interrupts should be the technique of last resort. Ideally your code can be interrupted most of the time and you deal with packet storms by having more available buffers. Unless you design goal is truly to be as small as possible - in that case you willingly trade space for performance.

    Having the client control the refresh rate is the way to go. Otherwise, you are just burning time checking for screen updates when probably nobody will care. You can probably get by with 200ms between updates easily; if a user can't tolerate that, then they are not going to like the performance penalty for being remote either. Trapping calls to INT 10 is a good idea too, but not just to force an update - you still want those batched. If everytime somebody writes a character you have to send the whole screen it's going to be really chatty. (Of course you could detect what they are doing with INT 10 and then just send the deltas .. but now you are trading better performance for space again.)


    -Mike

  9. #9

    Default

    while i mull over all these suggestions, you can try the program as it is now if you want. i think it works fairly well. the only thing is certain program (MSD.EXE for example) require int 9h to actually be pressed to register a keystroke and it doesn't do that. most programs are fine though.

    server for DOS:
    http://rubbermallet.org/remoter-server.zip

    client for windows:
    http://rubbermallet.org/remoter-client.zip


    the IP stack doesn't do DHCP yet, so before you run minitcp.com you'll need to run setip.exe which will let you modify the IP, subnet mask, and gateway IP it will use. run minitcp.com first, then remoter.com. right now it requires the packet driver to be on int 60h.

    for the client, once the server is running on a DOS machine just run remoter.exe with the IP address of the server on the command line. oh, and just a note... it only supports 80x25 text mode so far, and it wont work with an MDA.




    also, i know UDP isn't all that useful like TCP is, but if anybody wanted to know the interrupt calls for the MiniTCP TSR, right now they are:

    Code:
    MiniTCP interrupt calls
    =======================
    
    Call:
      AH = 00h (function: get local information)
    
    Return:
      DS:SI = Pointer to 18-byte network info array:
              Offset 0: Local IP address (4 bytes)
              Offset 4: Subnet mask (4 bytes)
              Offset 8: Gateway IP address (4 bytes)
              Offset 12: Local MAC address (6 bytes)
    
    =======================
    
    Call:
      AH = 01h (function: disable and uninstall MiniTCP)
    
    Return:
      Nothing.
    
    ======================
    
    Call:
      AH = 02h (function: send UDP packet)
      BX = Destination port
      CX = Length of data in bytes (up to 1472 bytes per pkt)
      DS:SI = Pointer to data buffer
      DX:DI = Pointer to 4-byte destination IP address
      ES = Source port
    
    Return:
      Nothing.
    
    =======================
    
    Call:
      AH = 03h (function: define callback pointer for UDP receive)
      BX:CX = Callback handler pointer (both NULL to disable)
    
    Return:
      Nothing.
    
    On callback:
      AX = Source port
      BX = Destination port
      CX = Length of Data in bytes
      DS:SI = Pointer to data buffer
      DX:DI = Pointer to 4-byte source IP address
    
    =======================
    the UDP callback is entered using the interrupt style, as in it pushes the flags, CS, and IP.. so when you return to need to use an iret. MiniTCP sits on int 61h.
    Last edited by Mike Chambers; August 7th, 2011 at 06:09 PM.
    My emulators!
    Fake86 8086/V20 PC emulator: http://sourceforge.net/p/fake86
    MoarNES Nintendo emulator: http://sourceforge.net/p/moarnes


  10. #10

    Default

    well, i feel stupid. i had uploaded the client without asciivga.dat which contains the character set! sorry, if anybody tried it. redownload from same link for fixed ZIP - http://rubbermallet.org/remoter-client.zip
    My emulators!
    Fake86 8086/V20 PC emulator: http://sourceforge.net/p/fake86
    MoarNES Nintendo emulator: http://sourceforge.net/p/moarnes


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •