C++实现Socket传输json封装的Mat
2018-08-17 20:52
267 查看
一般进行图片传输时,先用openCV把图片转换为Mat,然后封装到json当中,然后再从json中解析出来。这次是客户端向服务端传输。
Ps:客户端第一次发送一张图片,第二次发送两张图片,后面依次循环,转成Mat封装到json中,服务端接收并解析,如果是一张图片生成名称和相似度,如果是两张只生成相似度,封装到json,并返回至客户端(用于人脸识别的,读者可以根据自己的需要改动)
客户端:图片转换为Mat用imread即可,然后Mat通过imencode函数转为uchar*,再转换为string类型,然后通过c_str()函数转换为const char*,最后Base64编码存到json里面(我找的Base64.h编码只能用这个数据类型,所以这个转换数据类型卡了我很长时间,关键还是对数据类型不熟悉)
服务端:json里面的数据进行Base64解码成string,然后转换为uchar*,再通过imdecode转换成Mat,最后imshow显示或者imwrite保存(相当于客户端的逆过程)
openCV的配置过程在之前的博客中
json.hpp 下载地址https://github.com/nlohmann/json/tree/develop/include/nlohmann
一.服务端
main.cpp
[code]#include <iostream> #include <stdio.h> #include "Base64.h" #include <winsock2.h> #include "json1.hpp" #include <opencv2/opencv.hpp> #pragma comment(lib,"ws2_32.lib") using namespace cv; using json = nlohmann::json; char revData[3888888]; int main(int argc, char* argv[]) { //初始化WSA WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; } //创建套接字 SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (slisten == INVALID_SOCKET) { printf("socket error !"); return 0; } //绑定IP和端口 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind error !"); } //开始监听 if (listen(slisten, 5) == SOCKET_ERROR) { printf("listen error !"); return 0; } //循环接收数据 SOCKET sClient; sockaddr_in remoteAddr; int nAddrlen = sizeof(remoteAddr); //revData = (char*)malloc(sizeof(char) * 1000000); int i = 1; while (true) { printf("等待连接...\n"); sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen); if (sClient == INVALID_SOCKET) { printf("accept error !"); continue; } printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr)); int k = 1; while (true) { //接收数据 int ret = recv(sClient, revData, 3888888, 0); if (ret > 0) { revData[ret] = 0x00; json o = json::parse(revData); json j; for (json::iterator it = o.begin(); it != o.end(); ++it) { if (it.key() == "mat1") { Mat img_decode; std::string str_tmp = base64_decode(it.value()); std::vector<uchar> data(str_tmp.begin(), str_tmp.end()); img_decode = imdecode(data, CV_LOAD_IMAGE_COLOR); imshow("pic", img_decode); std::string num = std::to_string(k); imwrite("D:\\" + num + ".jpg", img_decode); k++; waitKey(10); } else if (it.key() == "mat2") { if (it.value() == "") { j["name"] = ""; j["similarity"] = ""; } else { Mat img_decode; std::string str_tmp = base64_decode(it.value()); std::vector<uchar> data(str_tmp.begin(), str_tmp.end()); img_decode = imdecode(data, CV_LOAD_IMAGE_COLOR); imshow("pic", img_decode); std::string num = std::to_string(k); imwrite("D:\\" + num + ".jpg", img_decode); k++; waitKey(10); j["similarity"] = ""; } } } //std::cout<< json::parse(revData)<< std::endl; //printf(revData); std::string s = j.dump(); const char * sendData; sendData = s.c_str(); //const char * sendData = "你好,TCP客户端!\n"; send(sClient, sendData, strlen(sendData), 0); } //发送数据 } } closesocket(sClient); closesocket(slisten); WSACleanup(); return 0; }
Base64.h
[code]#ifndef __BASE64_H__ #define __BASE64_H__ #include <iostream> #include <string> static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(const char c) { return (isalnum(c) || (c == '+') || (c == '/')); } std::string base64_encode(const char * bytes_to_encode, unsigned int in_len) { std::string ret; int i = 0; int j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (i = 0; (i <4); i++) { ret += base64_chars[char_array_4[i]]; } i = 0; } } if (i) { for (j = i; j < 3; j++) { char_array_3[j] = '\0'; } char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[3] = char_array_3[2] & 0x3f; for (j = 0; (j < i + 1); j++) { ret += base64_chars[char_array_4[j]]; } while ((i++ < 3)) { ret += '='; } } return ret; } std::string base64_decode(std::string const & encoded_string) { int in_len = (int)encoded_string.size(); int i = 0; int j = 0; int in_ = 0; unsigned char char_array_4[4], char_array_3[3]; std::string ret; while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i == 4) { for (i = 0; i <4; i++) char_array_4[i] = base64_chars.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret += char_array_3[i]; i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = base64_chars.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; } #endif
二.客户端
main.cpp
[code]#include<WINSOCK2.H> #include<STDIO.H> #include<iostream> #include<cstring> #include <string> #include <fstream> #include "Bash64.h" #include "json1.hpp" #include <opencv2/opencv.hpp> using namespace std; using json = nlohmann::json; using namespace cv; #pragma comment(lib, "ws2_32.lib") char chBuf1[3888888], chBuf2[3888888]; json readImg1() { json j; Mat image = imread("E:\\testImage\\4.jpg"); //存放自己图像的路径 std::vector<unsigned char> data_encode; int res = imencode(".jpg", image, data_encode); std::string str_encode(data_encode.begin(), data_encode.end()); const char* c = str_encode.c_str(); j["mat2"] = ""; j["mat1"] = base64_encode(c, str_encode.size()); //cout << j << endl; return j; } json readImg2() { json j; Mat image; const char* c; image = imread("E:\\testImage\\5.jpg"); //存放自己图像的路径 std::vector<unsigned char> data_encode; int res = imencode(".jpg", image, data_encode); std::string str_encode1(data_encode.begin(), data_encode.end()); c = str_encode1.c_str(); j["mat1"] = base64_encode(c, str_encode1.size()); image = imread("E:\\testImage\\6.jpg"); //存放自己图像的路径 //std::vector<unsigned char> data_encode; res = imencode(".jpg", image, data_encode); std::string str_encode2(data_encode.begin(), data_encode.end()); c = str_encode2.c_str(); j["mat2"] = base64_encode(c, str_encode2.size()); return j; } int main() { WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 0; } SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sclient == INVALID_SOCKET) { printf("invalid socket!"); return 0; } sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(8888); serAddr.sin_addr.S_un.S_addr = inet_addr("192.168.3.72"); if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) { //连接失败 printf("connect error !"); closesocket(sclient); return 0; } json data1; int i = 1; while (true) { if (i > 10) break; if (i % 2) data1 = readImg1(); else data1 = readImg2(); i++; std::string s = data1.dump(); const char * sendData; sendData = s.c_str(); //string转const char* //char * sendData = "你好,TCP服务端,我是客户端\n"; send(sclient, sendData, strlen(sendData), 0); //send()用来将数据由指定的socket传给对方主机 //int send(int s, const void * msg, int len, unsigned int flags) //s为已建立好连接的socket,msg指向数据内容,len则为数据长度,参数flags一般设0 //成功则返回实际传送出去的字符数,失败返回-1,错误原因存于error char recData[266680]; int ret = recv(sclient, recData, 266680, 0); if (ret>0) { recData[ret] = 0x00; printf(recData); printf("\n"); } } closesocket(sclient); WSACleanup(); system("pause"); return 0; }
Base64.h 上同
阅读更多相关文章推荐
- Android NDK 使用JSON实现数据封装传输
- c++ 应用socket实现C/S端文件的传输
- Android与Java 服务器使用Socket协议实现Json数据传输
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务2
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务1[使用IE浏览本页]
- c++ udp的socket通信使用jsoncpp传输
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务2[使用IE浏览本页]
- c++ 使用socket实现C/S端文件的下载传输
- C++中用Socket实现对结构体、长字符串和图片的传输
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务3[聊天室][使用IE浏览本页]
- c++实现封装socket
- c++ 使用socket实现C/S端文件的下载传输
- C++中用Socket实现对结构体、长字符串和图片的传输
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务4[聊天室][使用IE浏览本页]
- Socket编程实现文件的传输II(封装)
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务3[聊天室]
- c++ 使用socket实现C/S端文件的下载传输
- c++ 使用socket实现C/S端文件的下载传输
- .Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--使用封装的网络服务4[聊天室]
- c++ 使用socket实现C/S端文件的下载传输