Протокол HTTP действительно прост, на самом деле:
- клиент отправляет строку, содержащую имя метода HTTP, URL и версию протокола
- клиент отправляет заголовок RFC822, содержащий параметры запроса, и, если блок данных следует, подробности о блоке данных.
- клиент отправляет блок данных
- сервер отправляет строку, содержащую версию протокола, код состояния и сообщение
- сервер отправляет заголовок RFC822, содержащий параметры ответа, и, если блок данных следует (или клиент выполнил запрос HEAD), подробности о блоке данных
- сервер отправляет блок данных, если метод не HEAD.
- соединение оборвано или протокол перезапущен.
Обычно серверы понимают, по крайней мере, следующие методы:
- GET (клиент не отправляет блок данных, сервер отправляет блок данных)
- HEAD (аналогично GET, но на сервере отсутствует блок данных ответа)
- POST (клиент отправляет блок данных, сервер отвечает блоком данных)
- PUT (клиент отправляет блок данных, сервер не отправляет блок данных)
Существует некоторая подразумеваемая семантика в выборе метода, в которой запросы GET никогда не изменяют состояние сервера, и их результаты могут кэшироваться и использоваться повторно (что позволяет браузеру переходить назад и вперед между страницами), в то время как запросы POST делают изменить состояние сервера - кстати, это то, что вы делаете, когда загружаете файл.
Итак, чтобы отправить файл, подготовьте запрос POST или PUT (в зависимости от того, ожидаете ли вы ответный документ или достаточно простого кода статуса подтверждения), который состоит из строки запроса, заголовки которого содержат дополнительные информация о протоколе («Host:», «User-Agent:», ...), заголовки, описывающие файл («Content-Type:», «Content-Length:», ...), пустая строка и содержимое файла и отправьте его по TCP-соединению, затем прочитайте обратно строку состояния, заголовки ответа и файл ответа (если вы его запросили).