Skip to content

Commit 3592c6e

Browse files
committed
Initialize HTTP/3 bidirectional streaming project with Java server/client and Python client
1 parent 2ff7f27 commit 3592c6e

18 files changed

Lines changed: 1663 additions & 0 deletions

‎.gitignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
server.crt
2+
server.key
3+
build/
4+
venv/
5+
.gradle/

‎README.md‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# HTTP/3 Bidirectional Streaming Project
2+
3+
This project demonstrates HTTP/3 bidirectional streaming using Netty (Java) and aioquic (Python). It features a Java server that processes incoming data packets asynchronously and slowly to demonstrate flow control and bidirectional communication, with both Java and Python client implementations.
4+
5+
## Features
6+
- ✅ **HTTP/3 & QUIC**: Full HTTP/3 bidirectional streaming.
7+
- ✅ **Cross-Language**: Java Server with both Java and Python clients.
8+
- ✅ **Asynchronous Processing**: Server uses a thread pool to process packets without blocking the event loop.
9+
- ✅ **JSON Communication**: Structured data exchange using Jackson (Java) and json (Python).
10+
- ✅ **Flow Control**: Demonstrates handling of rapid packet bursts with slow processing.
11+
12+
## Project Structure
13+
```
14+
.
15+
├── src/main/java/
16+
│ ├── Http3BidirectionalStreamServer.java # Server implementation
17+
│ ├── Http3Client.java # Java Client implementation
18+
│ ├── ServerMain.java # Server entry point
19+
│ ├── ClientMain.java # Java Client entry point
20+
│ ├── DataPacket.java # Data model for packets
21+
│ ├── AckResponse.java # Response model for acknowledgments
22+
│ └── QuicTest.java # QUIC availability test
23+
├── python_client.py # Python Client implementation
24+
├── pyproject.toml # Python configuration & dependencies (Poetry)
25+
├── build.gradle # Gradle build configuration
26+
└── poetry.lock # Locked Python dependencies
27+
```
28+
29+
## Getting Started
30+
31+
### Prerequisites
32+
- **Java 21** or higher.
33+
- **Python 3.10** or higher (for the Python client).
34+
- **Poetry** (for Python dependency management).
35+
- **OpenSSL** (to generate certificates).
36+
37+
### 1. Generate SSL Certificates
38+
The HTTP/3 server requires an SSL certificate and private key to function. Run the following command in the project root to generate self-signed certificates:
39+
40+
```bash
41+
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=localhost"
42+
```
43+
44+
This will create `server.key` and `server.crt` in your current directory.
45+
46+
### 2. Setup Python Environment
47+
This project uses **Poetry** for Python dependency management (similar to Gradle for Java).
48+
49+
1. **Install Poetry** (if not already installed):
50+
```bash
51+
pip install poetry
52+
```
53+
54+
2. **Install Dependencies**:
55+
```bash
56+
poetry install
57+
```
58+
59+
### 3. Running the Server
60+
The server starts on port `9443` using the certificates generated in step 1.
61+
```bash
62+
./gradlew run
63+
```
64+
65+
### 4. Running the Clients
66+
67+
#### Java Client
68+
```bash
69+
./gradlew runClient
70+
```
71+
72+
#### Python Client
73+
```bash
74+
poetry run python python_client.py
75+
```
76+
77+
## Implementation Details
78+
79+
### Java Client Fixes
80+
The Java client has been optimized for:
81+
- **Correct Pipeline Setup**: Uses `Http3ClientConnectionHandler` and `Http3.newRequestStream` for proper HTTP/3 frame handling.
82+
- **Strict JSON Serialization**: Uses Jackson annotations to ensure JSON compatibility between Java and Python components.
83+
- **Resilient Deserialization**: Handles variations in JSON field names (e.g., `isFinal` vs `final`) gracefully.
84+
85+
### Server Behavior
86+
The server is designed to be "slow" by introducing a random delay (500ms - 1500ms) for each packet. This highlights the bidirectional nature of the protocol where the client can keep sending packets while waiting for individual ACKs to arrive out-of-order or delayed.
87+
88+
## Dependencies
89+
- **Netty Incubator HTTP/3 & QUIC**: For the core protocol implementation.
90+
- **Jackson Databind**: For JSON processing in Java.
91+
- **aioquic**: For the Python client implementation.

‎build.gradle‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
plugins {
2+
id 'java'
3+
id 'application'
4+
}
5+
6+
java {
7+
toolchain {
8+
languageVersion = JavaLanguageVersion.of(21)
9+
}
10+
}
11+
12+
repositories {
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
implementation 'io.netty.incubator:netty-incubator-codec-http3:0.0.30.Final'
18+
implementation 'io.netty.incubator:netty-incubator-codec-native-quic:0.0.74.Final:osx-x86_64'
19+
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
20+
}
21+
22+
application {
23+
mainClass = 'ServerMain'
24+
applicationDefaultJvmArgs = [
25+
'-Dio.netty.leakDetection.level=DISABLED',
26+
'-Djava.library.path=.',
27+
'--add-opens=java.base/java.nio=ALL-UNNAMED'
28+
]
29+
}
30+
31+
task testQuic(type: JavaExec) {
32+
classpath = sourceSets.main.runtimeClasspath
33+
mainClass = 'QuicTest'
34+
jvmArgs = [
35+
'-Dio.netty.leakDetection.level=DISABLED',
36+
'-Djava.library.path=.',
37+
'--add-opens=java.base/java.nio=ALL-UNNAMED'
38+
]
39+
}
40+
41+
task runClient(type: JavaExec) {
42+
classpath = sourceSets.main.runtimeClasspath
43+
mainClass = 'ClientMain'
44+
jvmArgs = [
45+
'-Dio.netty.leakDetection.level=DISABLED',
46+
'-Djava.library.path=.',
47+
'--add-opens=java.base/java.nio=ALL-UNNAMED'
48+
]
49+
}

‎gradle/wrapper/gradle-wrapper.jar‎

44.6 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)