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

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

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

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Q&A

解決済

1回答

2730閲覧

VS2015C++でwinsock,OpencvによるTCP画像送信プログラム

MOTOZOMBIE

総合スコア13

Visual Studio

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

0グッド

0クリップ

投稿2017/09/10 10:35

###前提・実現したいこと
私はネットワーク初心者です.環境は,VS2015C++でwinsockとOpencvを使ってプログラミングしています
実現したいことは,
・TCPのサーバでMat型の画像を読み込む.

・Mat型の画像をエンコードする

・サーバに接続したクライアントにエンコード画像を送る.

・クライアント側で,デコードする.

・画像を出力する
ということをしたいと考えています.
** !!! まだ実装段階でないのでスパゲティとなっております. !!!**

やっていて,すごく楽しい内容なので,これで躓きたくありません.
ですので,ぜひともご回答お願い致します!
###発生している問題

・クライアント側で,文字が最初の3文字しか受け取れない
・バッファのサイズを大きくすると,オーバーフローとなってしまう.
・サーバ側の, len = sizeof(client); の意味がわからない.

・スパゲティコード
###該当のソースコード

C++

1//サーバ側 2#include <iostream> 3#include <winsock2.h> 4#include <opencv2/opencv.hpp> 5#include <vector> 6#pragma comment(lib, "ws2_32.lib") 7 8#define BUFFER_SIZE 999999 9 10using namespace std; 11using namespace cv; 12 13int main(int argc, char *argv[]) 14{ 15 /* 宣言 */ 16 WSADATA wsaData; 17 SOCKET sock0; 18 SOCKET sock; 19 20 struct sockaddr_in addr; //自身のソケットの設定 21 struct sockaddr_in client; //相手のソケットの設定 22 int len; 23 24 Mat src = imread(argv[1]); 25 26 char buf[BUFFER_SIZE]; 27 vector<unsigned char> enc_buf; 28 29 int size = src.rows * src.cols; 30 31 /* 初期化 */ 32 // winsock2の初期化 33 WSAStartup(MAKEWORD(2, 0), &wsaData); 34 35 // ソケットの作成 36 sock0 = socket(AF_INET, SOCK_STREAM, 0); 37 // ソケットの設定 38 //アドレスファミリ 39 addr.sin_family = AF_INET; 40 //ポート番号 41 addr.sin_port = htons(12345); 42 //IPアドレス INADDR_ANY : どのアドレスからの接続でも受け入れる 43 addr.sin_addr.S_un.S_addr = INADDR_ANY; 44 45 //sock0にソケットの設定を埋め込む 46 bind(sock0, (struct sockaddr *)&addr, sizeof(addr)); 47 48 //エンコードの設定 49 vector<int> param = vector<int>(2); 50 //jpg : CV_IMWRITE_JPEG_QUALITY 51 //png : CV_IMWRITE_PNG_COMPRESSION 52 param[0] = CV_IMWRITE_JPEG_QUALITY; 53 //エンコードの画質 : 0 ~ 100 54 param[1] = 85; 55 56 // キューの作成 57 //listen(待つソケット,接続の最大キュー) 58 listen(sock0, 3); 59 60 /* メイン処理 */ 61 //入力画像をエンコード 62 imencode(".jpg", src, enc_buf, param); 63 Mat jpgimage = imdecode(enc_buf, CV_LOAD_IMAGE_COLOR); 64 65 //エンコード内容を300字表示 66 for (int i = 0; i < 300; i++) cout << enc_buf[i]; 67 cout << endl; 68 69 //srcが連続的なバイト列だったら、要素サイズ * 画像サイズを。違えば0を返す 70 cout << "Original Data Size: " << (src.isContinuous() ? (src.elemSize() * size) : 0) << " [byte]" << endl; 71 cout << "Encoded Image Size: " << enc_buf.size() << " [byte] (quality=" << param[1] << ")" << endl << endl; 72 while (true) { 73 len = sizeof(client); 74 //ソケット接続待機 75 //accept(受け取るソケット,クライアント情報,"不明") 76 sock = accept(sock0, (struct sockaddr *)&client, &len); 77 78 //相手のIP, portを表示 79 cout << "Cliant : IP = " << inet_ntoa(client.sin_addr) << endl; 80 cout << "Cliant : port = " << ntohs(client.sin_port) << endl << endl; 81 82 for (int i = 0; i < enc_buf.size(); i++) buf[i] = enc_buf[i]; 83 int check = sendto(sock, buf, enc_buf.size(), 0, (struct sockaddr *)& addr, sizeof(addr)); 84 } 85 //セッションの終了 86 closesocket(sock); 87 // winsock2の終了処理 88 WSACleanup(); 89 90 return 0; 91} 92

C++

1//クライアント側 2#include <iostream> 3#include <winsock2.h> 4#include <opencv2/opencv.hpp> 5#include <vector> 6#pragma comment(lib, "ws2_32.lib") 7 8#define BUFFER_SIZE 999999 9 10using namespace std; 11using namespace cv; 12 13int main() 14{ 15 WSADATA wsaData; 16 struct sockaddr_in server; 17 SOCKET sock; 18 19 char buf[BUFFER_SIZE]; 20 vector<unsigned char> enc_buf; 21 22 23 // winsock2の初期化 24 WSAStartup(MAKEWORD(2, 0), &wsaData); 25 26 // ソケットの作成 27 sock = socket(AF_INET, SOCK_STREAM, 0); 28 29 // 接続先指定用構造体の準備 30 server.sin_family = AF_INET; 31 server.sin_port = htons(12345); 32 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 33 34 // サーバに接続 35 connect(sock, (struct sockaddr *)&server, sizeof(server)); 36 37 38 //memset(メモリブロック(配列), どこの値から, どこまでか) 39 memset(buf, 0, BUFFER_SIZE); 40 41 //画像データ受信 42 recvfrom(sock, buf, BUFFER_SIZE, 0, NULL, NULL); 43 cout << "received : " << buf; 44 //for (int i = 0; i < sizeof(buf); i++) enc_buf[i] = buf[i]; 45 //Mat jpgimage = imdecode(enc_buf, CV_LOAD_IMAGE_COLOR); 46 //imwrite("jpgimg.jpg", jpgimage); 47 cin.get(); 48 49 // winsock2の終了処理 50 WSACleanup(); 51 52 cin.get(); 53 return 0; 54}

###実行結果
サーバイメージ説明
###試したこと
memset(buf, 0, BUFFER_SIZE);から,memset(buf, 0, 1);にした(メモリの総数を減らしたらどうなるかを試した).
→結果:同じ
len = sizeof(client)と,バッファのサイズに関しては,手を付けていない.

###補足情報(言語/FW/ツール等のバージョンなど)
・Visual Studio2015 C++
・OpenCV3.1 ←Nugetから入手
・winsock2.h

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

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

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

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

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

guest

回答1

0

ベストアンサー

・クライアント側で,文字が最初の3文字しか受け取れない

recvfrom命令はその時点でバッファに格納されているデータを読み出す命令です。指定したサイズのデータを読み出す命令ではありません。1回のsendto呼び出しで送信したデータが複数回に分かれて受信される事もありますし、逆に2回のsendto呼び出しで送信したデータが1回で受信される事もあります。必要なデータが揃うまで、recvfromを複数回呼び出してデータを結合するように修正して下さい。

ただ3バイトだけというのは、それはそれで異常です。見てみると「cout << "received : " << buf;」で出力していますが、4バイト目に0x00が格納されていませんか?C++ではバイト列中に含まれる0x00を文字列の終端として扱うので、バイナリデータを文字列系のAPIでは扱えませんよ。

・バッファのサイズを大きくすると,オーバーフローとなってしまう.
スタックオーバーフローのことですか?バッファをスタック上に作成しているようですが、スタックのサイズは通常1Mバイト程度でしかありません。ビルド時の設定で増やすことも出来ますが、スタック領域ではなくヒープ領域に確保するように直した方が良いでしょう。

・サーバ側の, len = sizeof(client); の意味がわからない.
socket APIはIPv4専用のAPIではありません。それ以外の様々な通信プルトコルでも使用します。そのためアドレスを表す構造体のサイズも固定ではなく、メモリサイズを引数として渡すように設計されています。

投稿2017/09/11 00:56

Kunihiro_Narita

総合スコア472

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

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

MOTOZOMBIE

2017/09/11 08:26 編集

ご回答ありがとうございます! 知りたいことを全て教えてくださって正直びっくりしました. >ただ3バイトだけというのは、それはそれで異常です。見てみると「cout << "received : " << buf;」で出力していますが、4バイト目に0x00が格納されていませんか? →全くもってそのとおりでした.バイナリデータにしてだすと,FF D8 FF E0 00とあり,0x00がありました!ありがとうございます! >スタックオーバーフローのことですか?バッファをスタック上に作成~ →この件に関しては,mallocというのを使って解決しようと思います! >socket APIはIPv4専用のAPIではありません。 →なるほど!たしかにそうですね!教えていただきありがとうございます! おかげで,画像を送信することに成功しました!本当にありがとうございました!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問