質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

1回答

3501閲覧

boost asioでmultipartのPOST

Lopn_

総合スコア50

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2018/05/01 05:32

boost asioを使用してmultipartでデータをPOSTしようとしているのですが、socket.writeをした後のresponseデータの受け取りができずに困っています

サーバはphpで動かしています
PHPのサーバはこのサイトを参考にして作成しました

cpp

1#include <iostream> 2#include <istream> 3#include <ostream> 4#include <string> 5#include <fstream> 6#include <cstdlib> 7 8#include <boost/asio.hpp> 9#include <boost/bind.hpp> 10#include <boost/lexical_cast.hpp> 11#include <boost/uuid/uuid.hpp> 12#include <boost/uuid/uuid_io.hpp> 13#include <boost/uuid/uuid_generators.hpp> 14 15std::string host = "localhost"; 16std::string path = "/dashboard/c/upload.php"; 17const char* file = "C:/Users/flatc/Desktop/5455875.jpg"; 18 19std::string CRLF = "\r\n"; 20 21void read_some_handler(const boost::system::error_code& error, boost::array<char, 128> buf, std::size_t len) { 22 std::cout.write(buf.data(), len); 23} 24 25void write_some_handler(const boost::system::error_code& error, std::size_t bytes_transferred) { 26 std::cout << bytes_transferred << std::endl; 27} 28 29int main() { 30 try { 31 boost::asio::io_service io_service; 32 boost::asio::ip::tcp::resolver resolver(io_service); 33 boost::asio::ip::tcp::resolver::query query(host, "http"); 34 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 35 36 boost::asio::ip::tcp::socket socket(io_service); 37 boost::asio::connect(socket, endpoint_iterator); 38 39 boost::asio::streambuf request; 40 std::ostream r(&request); 41 42 int size; 43 44 struct _stat buff; 45 int re = _stat(file, &buff); 46 if (re == 0) { 47 size = buff.st_size; 48 } 49 50 std::string boundary; 51 boost::uuids::uuid rstr = boost::uuids::random_generator()(); 52 boundary = boost::lexical_cast<std::string>(rstr); 53 54 /* 55 do { 56 boost::uuids::uuid rstr = boost::uuids::random_generator()(); 57 boundary = boost::lexical_cast<std::string>(rstr); 58 } while (img.find(boundary) != std::string::npos);*/ 59 60 std::stringstream pre, post; 61 int length; 62 63 pre << 64 "--" << boundary << CRLF << 65 "Content-Disposition: form-data; name=\"userfile\"; filename=\"5455875.jpg\"" << CRLF << 66 "Content-Type: application/octet-stream" << CRLF << 67 "Content-Transfer-Encoding: binary" << CRLF << CRLF; 68 69 std::cout << pre.str().c_str() << std::endl; 70 71 post << 72 CRLF << "--" << boundary << "--" << CRLF; 73 74 length = size + pre.str().size() + post.str().size(); 75 76 r << 77 "POST " << path << " HTTP/1.1" << CRLF << 78 "Host: " << host << CRLF << 79 "Content-Type: multipart/form-data; boundary=" << boundary << CRLF << 80 "Content-Length: " << boost::lexical_cast<std::string>(length) << CRLF << CRLF; 81 82 auto rr = request.data(); 83 84 socket.write_some(boost::asio::buffer(rr)); 85 socket.write_some(boost::asio::buffer(pre.str())); 86 87 std::ifstream ifs(file, std::ios::binary | std::ios::in); 88 89 char buf[512]; 90 while (ifs.read(buf, 512)) { 91 socket.write_some(boost::asio::buffer(buf)); 92 } 93 ifs.close(); 94 95 socket.write_some(boost::asio::buffer(post.str())); 96 97 boost::asio::streambuf response; 98 boost::asio::read_until(socket, response, CRLF); 99 100 std::istream res(&response); 101 std::string http_version; 102 unsigned int status_code; 103 std::string buf_; 104 105 res >> http_version; 106 res >> status_code; 107 108 std::cout << status_code << std::endl; 109 110 if (status_code != 200) { 111 std::cout << "Connection Error!" << std::endl; 112 std::cout << "Status code: " << status_code << std::endl;; 113 } 114 else { 115 while (getline(res, buf_)) { 116 std::cout << buf_ << std::endl; 117 } 118 119 std::cout << std::endl; 120 } 121 } 122 catch (std::exception &e) { 123 std::cerr << e.what() << std::endl; 124 } 125 126 getchar(); 127 128 return 0; 129}

現状は、writeはできている(?)のでwriteが終わった段階でプログラムを終了すると画像は送られています。
responseデータの受け取りはどのようにすればいいのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

すでに解決されているかもしれませんが、以下の読み込み部分でループ条件に問題があります。

C++

1 char buf[512]; 2 while (ifs.read(buf, 512)) { 3 socket.write_some(boost::asio::buffer(buf)); 4 }

以下のように EOF を判定しなければ、ファイルの最後の部分が送信できません。

C++

1 char buf[512]; 2 while (!ifs.eof()) { 3 ifs.read(buf, 512); 4 socket.write_some(boost::asio::buffer(buf, ifs.gcount())); 5 }

Content-Length ヘッダ分のデータ量を送信できていないため、HTTP レスポンスが返ってきていないようです。上記の修正でレスポンスは受け取れるようになりました。

投稿2018/05/07 15:21

atata0319

総合スコア881

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lopn_

2018/05/08 10:38

eof確認忘れていました(;^ω^) ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問