Projects I’ve worked on in graduate-level course Network Programming in NCTU in Fall 2015.
This course was completed on Jan., 2016. 4 projects in total.

  • NP HW4: SOCKS4 Server & Client

    In this network programming homework, we are asked to build SOCKS4 server and client and combine HW3 to demo.

    Spec is not included; however, the basic architecture can be illustrated as follows: rbs_diagram

    There are some notable ideas I came up with:

    For SOCKS client (CGI):

    • Same as HW3. Just need to send SOCK4 requset and handle SOCK4 reply.

    For SOCKS Server:

    - CONNECT mode procedure:

    accept → read SOCKS req → check firewall rules →
    connect to dest host → send SOCKS reply → redirect data
    

    - BIND mode procedure:

    accept → read SOCKS req → check firewall rules →
    bind socket → listen → send SOCKS reply → 
    accpet from server → send SOCKS reply (to original client) → redirect data
    

    - When redirecting data, should avoid using strncpy since it may contain '\0' in data, which occasionally leads to data error (less bytes are copied than expected).
    - When bind with system-assigned port, give 0 to sockaddr_in.sin_port.

    Demo video:
    np_hw4_demo

    Source → cyhuang1230/NetworkProgramming

    For SOCKS client (CGI):
    Please look for NP_project4_Server.cpp.
    To try: make hw4_cgi , upload to a HTTP server and run <BASE_URL>/hw4.cgi.

    For SOCKS server:
    Please look for NP_project4_Server.cpp.
    To try: make hw4_server and run ./np_hw4.

  • NP HW3: Remote Batch System (RBS)

    In this network programming homework, we are asked to build a Remote Batch System (RBS). It’s actually a combination of client and server, whose diagram can be drawn as follows:

    rbs_diagram

    As required in spec(hw3Spec.txt), we have to write three programs:

    1. CGI: a webpage(hw3.cgi) that displays server’s response dynamically.
    2. HTTP Server: a cpp program that runs as a HTTP server.
    3. Winsock: a combination of 1. and 2. but using Winsock.

    For more details, please refer to hw3Spec.txt in the repository (cyhuang1230/NetworkProgramming).

    There are some notable ideas I came up with and described as follows.

    For CGI (Part I):

    • Write may fail. Write a wrapper class to handle this.
    • Parsing query string needs to be handled carefully.
    • Since we’re client now, doesn’t matter which port to use, i.e. no need to bind anymore!
    • Try using flag(bitwise comparison) instead of individually specifying each property in log function.
    • Output recerived from servers should be handled(e.g. \n, <, >, &, ', ") since JavaScript has different escape characters than C. Also, the order of processing characters matters.
    • Most importantly, non-blocking client design.
          [1] connect may be blocked due to slow connection.
              => Set O_NONBLOCK to sockfd
          [2] Client program may block (e.g. sleep)
              => Don’t wait for response (i.e. read) after write to server. Instead, use select to check when the response is ready to read.

    For HTTP Server (Part II):

    • Use select to accept connections.
    • Fork a child process to handle request.
    • Plain text file can be read & write directly. Content type needs to be set properly.
    • CGI needs to be execed. => dup its STDOUT_FILENO to sockfd.

    For Winsock (Part III):

    • Same logic as Berkeley Socket version.
    • To read file, use ReadFile instead of ReadFileEx (I encountered pointer error)
    • Keep track of doneMachines. When done (== numberOfMachines), close socket and print footer.
    • I like Berkeley Socket much more than Winsock :(

    Demo video:
    np_hw3_demo

    Source → cyhuang1230/NetworkProgramming

    For part I (CGI):
    Please look for NP_project3_1.cpp.
    To try: make hw3_1_debug, upload to a HTTP server and run <BASE_URL>/hw3.cgi.

    For part II (HTTP Server):
    Please look for NP_project3_2.cpp.
    To try: make hw3_2_debug and run ./np_hw3.

    For part III (Winsock):
    Please look for NP_project3_3.cpp. Run with Visual Studio is recommended.

  • NP HW2: Remote Working Ground (RWG)

    In this network programming homework, we are asked to build a remote working ground (RWG), which is actually a combination of hw1 and chat & public pipe function.

    According to the spec(hw2Spec.txt), we need to write two programs:

    1. Use the single-process concurrent paradigm.
    2. Use the concurrent connection-oriented paradigm with shared memory.

    For more details, please refer to hw2Spec.txt in the repository (cyhuang1230/NetworkProgramming).

    There are some notable ideas I came up with and described as follows.
    (I will start with version II since I wrote that first :P)

    For concurrent version:

    • Keep track of client’s data (e.g. sockfd, pid…) so that we can send msg to each client.
    • Store client data & messages in shared memory so let every child can read.
    • Create additional MAX_USER(# of user) blocks of shm to store direct msg (or broadcst msg).
    • There’s no way server can be closed properly (must end by Ctrl+C), so, in order not to leave any shm unrelaesed, we won’t shmget until the first client is connected, and free shm when all clients are disconnected.
      → To keep track of the number of children, sa_handler needs to be implemented separately.
      → Furthermore, MUST reset sa_handler in the child process so that won’t mistakenly detach shm later when exec.
    • Use signal SIGUSR1 to notify other process there’s a new msg to write.
    • Semaphore on public pipes to prevent concurrent issue. (Same create/release idea as shm.)
    • Use FIFO, a.k.a Named pipe, to implement public pipe. [No need to store in shm].
    • Implement a generic function to send msg to a specific user.
      Function hierarchy:
      sendRawMsgToClienttell
      sendRawMsgToClientbroadcastRawMsgyell/name/who

    For single-process version:

    • Basically same structure as ver. II, but as a single-process program, we don’t need any shm or semaphore, which makes it much easier, yayyy!.
    • Only involves one huge adjustment.
      Consider the following input:
    [Client 1] % ls |1
    [Client 2] % ls |1
    [Client 1] % cat
    [Client 2] (empty) <- stucked, prompt won't display
    

        This error is caused by the way we decide input.
        → We can no longer expect the whole input with numbered-pipe can be got in one while loop.
        → Instead, we have to check input line by line, and keep track of input-related information.

    Demo video: (client is not included in the repo)
    np_hw2_demo

    Source → cyhuang1230/NetworkProgramming

    For ver. I (Single process):
    Please look for NP_project2_Single.cpp.
    To try: make hw2s and run ./np_hw2s.
    *Try with debug message: make hw2_debugs and run ./np_hw2s.

    For ver. II (Concurrent):
    Please look for NP_project2_Concurrent.cpp.
    To try: make hw2 and run ./np_hw2.
    *Try with debug message: make hw2_debug and run ./np_hw2.

    *Debug version is complied with -g, which may use gdb np_hw2(s) to debug.

  • NP HW1: Remote Access System (RAS)

    In this network programming homework, we were asked to build a remote access system. It’s kind of like a shell on the server side.

    For more details, please refer to hw1Spec.txt in the repository (cyhuang1230/NetworkProgramming).

    Demo video:
    np_hw1_demo

    Source → cyhuang1230/NetworkProgramming

    Please look for NP_project1.cpp.
    To try: make hw1 and run ./np_hw1.
    Try with debug message: make hw1_debug and run ./np_hw1.