C++实现Socket传输json封装的Mat

一般进行图片传输时,先用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

#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

#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

#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 上同

猜你喜欢

转载自blog.csdn.net/weixin_42755375/article/details/81783125