Skip to content

matthiasgreen/chatsystem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

90 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chat System

This school project is a distributed peer-to-peer chat system written in Java using Maven build tools. It is intented to allow employees to communicate on the local network without a centralized server. More information and detailed specifications can be found under doc/uml.

Running the released (shaded) jar

java -jar chat-system-1.0-SNAPSHOT.jar

This will run the chat system in GUI mode, on ports 8000-8002, and will attempt to find an IP address with internet access to run on. This should be the desired mode of operation for most users.

However, you can supply the following arguments to the jar to change the behavior:

  • -c : Run in CLI mode
  • -a [ip] : Run on a specific IP address
  • -p [port] : Run on ports [port]-[port+2]
  • -f [file] : Use a specific database file. Otherwise it default to the ip address.

Example:

java -jar chat-system-1.0-SNAPSHOT.jar -a 192.168.0.1 -c

Building the shaded jar for release

This is done automatically in .github/workflows/release.yaml, but can be done manually by using the shade profile defined at the bottom of pom.xml.

mvn package -Pshade

Building and running during development

To build the project, you need to have Maven installed.

Some scripts are supplied for convenience under ./bin.

Note that the start_gui and start_cli scripts work differently on different systems due to differences in socket implementations.

./bin/update_cp.sh # Installs dependencies and saves the classpath to classpath.txt

./bin/reset.sh # Deletes the databases

./bin/build.sh # Build and packages into a jar, skipping all tests

mvn test # Run all tests

# Windows
.\bin\start_gui.ps1 2 # Starts 2 instances of the GUI application on 127.0.0.1 and 127.0.0.2

.\bin\start_cli.ps1 1 # Start one instance of the CLI application on 127.0.0.1
.\bin\start_cli.ps1 2 # Start one instance of the CLI application on 127.0.0.2

# Linux
./bin/start_gui.sh # Starts one instance of the application with default settings.

./bin/start_cli.sh # Starts one instance of the application in CLI mode with default settings.

To start the application without the scripts (on Linux):

classpath=$(cat classpath.txt)
java -cp "target/chatsystem-1.0-SNAPSHOT.jar:$classpath" com.mgreen.Main <options>

Design choices

Packages

The project is divided into the following packages:

  • com.mgreen
    • Contains the main class which parses command line arguments and starts the GUI or CLI application
    • .models
      • Contains the data classes that are stored in the database
    • .database
      • Contains DAOs (direct access objects) that can be subclassed for easy access to the database, along with other utilities
    • .communication
      • Contains different message types and logic to serialize and deserialize them
    • .user
      • .storage
        • Contains logic to store user data in database and in memory
      • .discovery
        • Contains logic to discover other instances on the network and select usernames
    • .message
      • .storage
        • Contains logic to store messages in database
      • .exchange
        • Contains logic to exchange messages between instances
    • .network
      • Contains the TCP and UDP servers and clients
    • .views
      • Contains interfaces for views
      • .cli
        • Contains the CLI views
      • .swing
        • Contains the GUI views
    • .controllers
      • Contains the controllers that link the views to the services

MVC

The project follows an improved MVC architecture:

  • Models are pure data classes, with minimal methods
  • Services under com.mgreen.user and com.mgreen.message contain the business logic and interact with the models
  • Views allow for user interaction and call the controllers
  • Controllers link the views to the services

Data serialisation

This project currently serializes class instances implementing com.mgreen.communication.protocol.Message to bytes. These can easily be reconstructed by casting the deserialized object to Message. This approach was chosen for its simplicity and ease of use. However, it has some downsides, such as the lack of a communication standard and low compatibility between different versions of the software.

Network communication

In order to simplify the network communication, I chose to use two different constant ports for UDP communication. Each message type specifies which port to be sent to. Messages which can be handled independently (CheckUsernameMessage, SetOnlineMessage) are sent to the passive server on port n+1. Messages that need to be handled along with other messages from other instances (CheckUsernameResponse, SetOnlineResponse) are send to the active client/server on port n+2. A TCP server is also running on port n+3, for "chat" connections between two instances.

Database

The project uses SQLite for simplicity. The name of the .db file is important for testing (to avoid having a shared database), so we default to the IP address of the instance. A static DatabaseConnectionManager class is used to get the connection, and DAO classes are used to access each table.

TODO

  • Allow users to change username and delete old contacts/messages.
  • Allow users to send images/files.
  • Put the database file in a better location.
  • Add more unit tests.
  • Document view classes.
  • Improve CLI views.
  • QA testing.

Development notes

  • Local network + IP address detection

    • Q: Which network to broadcast on?
      • Could broadcast on 255.255.255.255 to broadcast on all networks connected to device
        • Problem: Can't get ip address on the network, and we want ip address for device identification
      • Ask administrator/user to input network name and/or IP address (Optional solution)
      • For all local networks, run checks such (networkInterface.isUp) then (Selected solution)
        • For all addresses on this network
          • Check if ipv4 and address.isReachable
            • Try to ping google
              • Select this network and address
  • Database management:

    • Using SQLite for simplicity
    • Name of .db file is important for testing (avoid shared db), so we choose ip address
    • Static class to get connection
    • DAO classes for each table
  • Communication protocol

    • Choices
      • Use some JSON/XML library and define schemas for our messages
        • +Communication standard
        • -Need external dependency, custom serializer + validator
      • Use .properties
        • +No need for external dependency
        • -Custom serializer + validator
      • Serialize class instances to bytes
        • +Easy, just need messages to implement Serializable
        • -Versioning more difficult, not a communication standard
    • Chose serialize to bytes since it's so simple (Selected solution)
      • interface Message extends Serializable
        • implement to create new message type
      • MessageContainer = Message + Metadata
        • Easier to deserialize because of casting
  • TCP/UDP client/servers

    • UDP:
      • One "passive" server running on port 8000
        • For "background" tasks (responding to UsernameOK and Connection)
      • One "active" socket running on port 8001
        • For "active" tasks (broadcasting then awaiting all responses)
    • TCP:
      • One TCP Server running on port 8002
      • When TCP connects, creates a TCPConnectionHandler to handle that connection
      • Class also allows us to connect to others, returning a TCPConnectionHandler
    • Each message type specifies which port to be sent to
  • Architecture

    • Instead of just MVC, we do Model < DAO < Service < Controller > View
    • Model is just pure "dataclass"
    • DAO handles DB operations
    • Service handles business logic

About

Peer to peer chat system school project written in Java

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages