Skip to content

Term project for Internet Computing, Spring 2022, aiming to implement HTTP client and server with Java socket API.

Notifications You must be signed in to change notification settings

NintenSAGA/HTTP-Client-Server-for-Java

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTTP Client/Server for Java

JDK Platform

由 Java Socket API 实现的简单 HTTP Client 与 Http Server

Info

开发日志: DevLog.md

测试用数据集: Data.zip

1. 概览

1.1 环境

本项目基于 JDK 17.0 编写,由 Maven 构造。

1.2 依赖

Scope GroupId ArtifactId Version
Provided org.projectlombok lombok 1.18.22
Compile org.json json 20220320
Test org.junit.jupiter junit-jupiter-engine 5.8.2

1.3 构建与运行

1.3.1 构建

  • HttpClient: mvn package -Pclient
  • HttpServer: mvn package -Pserver

1.3.2 运行

最终产品为 jar 文件,通过 java -jar [NAME].jar 运行。

2. 使用

2.1 外部文件

Data 及其子目录会在 HttpClient 或 HttpServer 启动时被自动创建于 jar 文件所在目录,结构如下:

Data
├── Client
│   └── Cache   // Client的缓存目录
└── Server
    ├── Cache   // Server的缓存目录(未使用)
    └── Static  // Server的静态文件存放目录

2.2 HttpServer

2.2.1 执行指令

java -jar /path/to/HttpServer.jar [OPTIONS]...

2.2.2 具体语法

SYNOPSIS
    ~   [-a <ADDRESS>] [-p <PORT>] [--keep-alive]
        [-t <TIMEOUT>] [--help]
        
OPTIONS
    --help          Show this help information.

    -a <ADDRESS>    Bind the server to the specified IPv4 address.
                    The default value is 127.0.0.1
    
    -p <PORT>       Bind the server to the specified port number.
                    The default value is 8080
                    
    --keep-alive    Enable keep-alive.
    
    -t <TIMEOUT>    Socket timeout.
                    The default value is 10000

2.2.3 启动信息

若运行正常,则会显示启动信息,包含:

  • Server 运行日志
  • 预设 URL Mapping 信息
  • 静态文件读取目录

如下所示:

SERVER: Preset mappings:
/register, methods: [POST]
/status, methods: [GET]
/login, methods: [GET]
/logout, methods: [GET]
/test, methods: [GET]
/missing, methods: [GET,POST]
/moved, methods: [GET]
SERVER: Server bound to /127.0.0.1:8080
SERVER: Reading static files from: [file:///.../Data/Server/Static]
SERVER: The server is now running

2.3 HttpClient

2.3.1 执行指令

java -jar /path/to/HttpClient.jar <URL> [OPTIONS]...

2.3.2 具体语法

SYNOPSIS
    ~   <URL>
        [-m <METHOD>] [--keep-alive] [-b <text>]
        [-h <headers>...] [--help]
        
URL
    Using the generic URI syntax of:
    http://<HOSTNAME>[:PORT][/PATH][?QUERY]
    e.g.: http://jyywiki.cn/OS/2020/, http://127.0.0.1:8080/help/, http://www.google.com/search?q=uri
    The default value of the port number is 80.
    Only support HTTP protocol (not HTTPS).
    
OPTIONS
    --help          Show this help information.

    -m <METHOD>     Send with the specified web method.
                    Only supports GET and POST.
                    The default value is GET.
                    
    --keep-alive    Enable keep-alive.
    
    -b <text>       Plain text body.
    
    -h <header>...  Send with the specified headers.
                    Syntax: <key>:<value>
                    e.g.: User-Agent:AbaAba/0.1

2.3.3 执行信息

若执行正常,则会显示

  • Client 执行日志
  • HTTP Request Message 原信息
  • HTTP Response Message 原信息

其中原信息包含:

  • Startline
  • Headers
  • Body
    • 若为 text/plain 则直接显示
    • 否则存储在缓存目录中,显示文件路径

如下所示:

/* 直接显示 Body 内容 */

CLIENT: Client has connect to the host
SOCKET[localhost127.0.0.1:8080]: Message sent 0.097656 KB

>> ==================== HTTP Request Message ==================== <<
>> GET /test HTTP/1.1
>> Accept: */*
>> User-Agent: Wget/1.21.3
>> Host: localhost
>> Accept-Encoding: gzip
>>
CLIENT: Status code received: 200
CLIENT: Handle returned directly...
CLIENT: Request complete

<< ==================== HTTP Response Message ==================== >>
<< HTTP/1.1 200 OK
<< date: Tue, 24 May 2022 03:54:16 GMT
<< server: nju_ic
<< content-encoding: gzip
<< connection: keep-alive
<< content-type: text/plain; charset=UTF-8
<<
<< You got the place!!!
/* 显示 Body 存储路径 */

>> ==================== HTTP Request Message ==================== <<
>> GET /OS/2022/ HTTP/1.1
>> Accept: */*
>> User-Agent: Wget/1.21.3
>> If-Modified-Since: Sun, 22 May 2022 11:13:51 GMT
>> Host: jyywiki.cn
>> Accept-Encoding: gzip
>>
CLIENT: Status code received: 200
CLIENT: Handle returned directly...
CLIENT: Request complete

<< ==================== HTTP Response Message ==================== >>
<< HTTP/1.1 200 OK
<< date: Tue, 24 May 2022 03:56:37 GMT
<< server: nginx/1.18.0 (Ubuntu)
<< content-encoding: gzip
<< content-type: text/html; charset=utf-8
<< connection: keep-alive
<< Content-Length: 16876
<<
<< Body saved at:
<< file:///.../Data/Client/Cache/jyywiki.cn/OS/2022/index/cache.html

3. 功能

HttpServer 与 HttpClient 均采用 Java NIO.2 模型进行开发,使用了 java.nio.channels.AsynchronousServerSocketChanneljava.nio.channels.AsynchronousSocketChannel 等类。

3.1 HttpServer

3.1.1 支持 GETPOST 请求

相关测试: LoginSystemTests

GET POST

3.1.2 支持以下状态码:

  • 200 OK

200

  • 301 Moved Permanently

301

  • 302 Found

302

  • 304 Not Modified

304

  • 404 Not Found

404

  • 405 Method Not Allowed

405

  • 500 Internal Server Error

500

  • 505 HTTP Version Not Supported

505

3.1.3 支持长连接 (Keep-Alive)

相关测试:KeepAliveTest

Keep-Alive

3.1.4 支持MIME类型:

已测试过的全部类型: mime.json

理论支持任意文件传输

  • HTML: text/html

HTML

  • png: image/png

PNG

  • mp4: video/mp4

MP4

  • svg: image/svg+xml

SVG

3.1.5 支持注册、登录、状态保持系统

相关测试: LoginSystemTests

  1. 用户注册

loginsys_1

  1. 检查登录状态

loginsys_2

  1. 登出

loginsys_3

  1. 检查登录状态

loginsys_4

  1. 登录

loginsys_5

3.2 HttpClient

3.2.1 在CLI界面显示 Http Request&Response Message

相关测试:WANTest

client_cli

3.2.2 对 Status code 301, 302, 304 的处理

相关测试:RequestTest

  1. 301 Moved

301

  1. 302 Found

302

  1. 304 Not Modified

304

3.3 其他

4. 代码结构

main
├── java
│   └── edu.nju.http
│        ├── client  /* Client Package */
│        │   ├── ClientDriver.java      // main 函数入口
│        │   ├── HttpClient.java        // 程序主轴
│        │   └── StatusHandler.java     // Status code 处理类
│        ├── exception  /* Exception Package */
│        │   ├── InvalidCommandException.java   
│        │   │   // 用于 CLI,提示指令不合法
│        │   └── InvalidMessageException.java
│        │       // 用于 Message Parser,提示解析错误
│        ├── message /* Message Package */
│        │   ├── HttpMessage.java           // 抽象类
│        │   ├── HttpRequestMessage.java    // 继承 HttpMessage
│        │   ├── HttpResponseMessage.java   // 继承 HttpMessage
│        │   ├── MessageHelper.java         // 工具类
│        │   ├── ResponseMessageFactory.java
│        │   │      // Http Response Message 制造工厂
│        │   ├── consts /* Constant Package */
│        │   │   ├── Headers.java       // Header 常量类
│        │   │   └── WebMethods.java    // Method 常量类
│        │   ├── packer /* Packer Package */
│        │   │   ├── MessagePacker.java     
│        │   │   │   // 包装并发送 Http Message
│        │   │   └── encode
│        │   │       │ /* Content-Encoding          */
│        │   │       │ /* & Transfer-Encoding 策略类 */ 
│        │   │       ├── ContentGzipEncodeStrategy.java
│        │   │       ├── EncodeStrategy.java
│        │   │       ├── SourceEncodeStrategy.java
│        │   │       ├── TransChunkedEncodeStrategy.java
│        │   │       └── TransContentLengthEncodeStrategy.java
│        │   └── parser /* Parser Package */
│        │       ├── CustomizedReader.java  // 自制字节流读取器
│        │       ├── MessageParser.java // 解析并接收 Http Message
│        │       ├── contentdecode  
│        │       │   │ /* Content-Encoding 策略类 */
│        │       │   ├── ContentDecodeStrategy.java
│        │       │   └── ContentGzipDecodeStrategy.java
│        │       └── transdecode
│        │           │ /* Transfer-Encoding 策略类 */
│        │           ├── TransChunkedDecodeStrategy.java
│        │           ├── TransContentLengthDecodeStrategy.java
│        │           └── TransDecodeStrategy.java
│        ├── server /* Server Package */
│        │   ├── HttpServer.java    // 程序主循环
│        │   ├── ServerDriver.java  // main 函数入口
│        │   ├── TargetHandler.java // Target 处理类
│        │   └── target /* Target Package     */
│        │       │     /*  包含各 Mapping 方法 */
│        │       ├──TargetSet.java   
│        │       │  // 抽象类,其他类应继承此类
│        │       ├── Common.java
│        │       ├── Html.java
│        │       ├── LoginSystem.java
│        │       └── Mapping.java
│        └── util /* Utility Package */
│            ├── ArgIterator.java   // 参数遍历器,用于 CLI
│            ├── Config.java        // 包含各参数信息
│            └── Log.java           // 调试方法类
└── resources
    ├── default_status_text.json    // 默认 Status Code 对应文字
    ├── global_headers.json         // 默认 Server Headers
    ├── mime.json           // Suffix -> Content-Type 映射
    └── target_path.json    // Target 类注册表 
                            //( 用于在 Target Handler 初始化时用 
                            //   Reflection 自动装配 )

About

Term project for Internet Computing, Spring 2022, aiming to implement HTTP client and server with Java socket API.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages