c++实现socket以json格式传输图片

c++实现socket以json格式传输图片

整体参考https://blog.csdn.net/weixin_42755375/article/details/81590967
细节1参考 https://blog.csdn.net/weixin_42731241/article/details/81589589
细节2参考 https://www.cnblogs.com/yuqiao/p/5786427.html

一、主要任务:

1、C++实现socket通信
2、socket传输数据要封装成json格式
3、json传输字符串
4、json传输图片

二、大致流程:

客户端读取图片,经过Base64编码,转成字符串的形式,保存在json中,通过socket传到服务端,然后Base64解码,再转换成图片

三、客户端函数细节

前言—什么是socket(套接字)?

socket是使用标准Unix文件描述符(file descriptor)和其它程序通讯的方式
利用系统调用socket(),它返回套接字描述符(socket descriptor),然后再通过它来进行send()和recv()调用。

1.strcpy函数

C++的strcpy()用于字符串复制,用法是传入2个字符数组指针来执行,如strcpy(a,b)是将b指向的字符串复制到a指向的空间中。
详细用法参考

2、fread和fwrite函数

函数功能:用来读取一个数据块
一般调用形式:
fread(buffer,size,count,fp)
fwrite(buffer,size,count,fp)
详细用法参考

3、base64_encode和base64_decode

base64_encode(const char *bytes_to_encode, unsigned int in_len)
返回string
bytes_to_encode—需要编码的数据集
in_len—元素的个数

4、函数1、2、3连起来去理解把图片打包成json对象的过程

std::string chFileIn1 = "E:\\"+num+".jpg";

strcpy(chFileIn3, chFileIn1.c_str());

fIn1 = fopen(chFileIn3, "rb");

//fread()读取成功返回值为实际读回的数据个数(单位为Byte)
nRead1 = fread(chBuf1, sizeof(char), 3888888, fIn1);

//读取的内容做base64编码,返回string
//要编码的部分是chBuf1,编码元素的个数是nRead1
string imgBase64_1 = base64_encode(chBuf1, nRead1);

//封装进json
json data1;
data1["imgA"] = imgBase64_1;

fclose(fIn1);

5、socket函数

SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
winsock库里的函数,创建一个套接字,采用tcp连接

6、inet_addr函数

作用是IP地址格式转换

unsigned long ip = inet_addr("127.0.0.1");
printf("%ld\n", ip);
>>>1677343

参考

7、send函数—TCP类型的数据发送

int send(int sockfd, const void *msg, int len, int flags)
sockfd – 已建立好连接的socket。
msg – 待发送数据的缓冲区。
len – 待发送数据的字节长度。
flags – 一般情况下置为0。

8、recv函数—TCP类型的数据接收

int recv(int sockfd, void *buf, int len, unsigned int flags)
sockefd – 接收端套接字描述符(非监听描述符);
buf – 接收缓冲区的基地址;
len – 以字节计算的接收缓冲区长度;
flags – 一般情况下置为0。

这两个函数用于流式套接字或者数据报套接字的通讯。

9、函数5、6、7、8连起来理解

OCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//imgBase64_1就是4中解释的最终封装后的json
data1["imgA"] = imgBase64_1;
std::string s = data1.dump();
const char * sendData;
sendData = s.c_str(); 
send(sclient, sendData, strlen(sendData), 0);

10、connect()程序

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
sockfd是系统调用socket()返回的套接字文件描述符
serv_addr是保存着目的地端口和ip地址的数据结构struct socket
addelen设置为sizeof(struct sockaddr)
参考1
参考2

作用就是通过用户告诉的端口连接到目的IP
客户端的connect函数和服务端的accept函数是一对好基友,如果客户端没有去connect,那么服务器端的accept会一直等待

四、服务端函数细节

1、bind函数
作用是将套接字和机器上的一定的端口关联起来

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
sockfd 是调用 socket 返回的文件描述符。my_addr 是指向数据结构 struct sockaddr 的指针,它保存你的地址(即端口和 IP 地址) 信息。 addrlen 设置为 sizeof(struct sockaddr)。

2、listen函数

int listen(int sockfd, int backlog);
sockfd 是调用 socket() 返回的套接字文件描述符。backlog 是在进入 队列中允许的连接数目。
进入的连接是在队列中一直等待直 到你接受 (accept() )连接。它们的数目限制于队列的允许。 大多数系统的允许数目是20,你也可以设置为5到10。

3、accept函数

int accept(int sockfd, void *addr, int *addrlen);
addr 是个指 向局部的数据结构 sockaddr_in 的指针。这是要求接入的信息所要去的地 方(你可以测定那个地址在那个端口呼叫你)。

五、工程代码

1、免费 https://blog.csdn.net/weixin_42755375/article/details/81590967
2、收积分 https://download.csdn.net/download/weixin_42755375/10597950?utm_source=bbsseo
两个代码是同一个人写的,是一模一样的,
只不过一个免费,需要自己稍微整理;一个收积分,可以直接下载整个工程

六、bug解决

1、VS 2017新建项目编译时出现 找不到 Windows SDK 版本10.0.请安装所需的版本的 Windows SDK 或者在项目属性页的问题解决方案

解决:右键项目解决方案—重定解决方案目标—重定向项目—确定
参考1

2、无法找到源文件 winsock.h,stdio.h
其实问题2和问题1是同一个原因

解决办法:
控制面板—程序—选择更改visual studio 2017
进入visual studio installer,找到“使用C++的桌面开发”,勾掉右上角的勾选,然后再重新勾选上,有更新的话可以先更新
参考1

3、error C4996: ‘strcpy’: This function or variable may be unsafe. Consider using strcpy_s instead.

出现这个错误时,是因为strcpy函数不安全造成的溢出
解决办法:右键项目—属性—C/C++—预处理器—预处理器定义
编辑,在里面加入一段代码:
_CRT_SECURE_NO_WARNINGS
点击确定
参考2

4、VS2017中C4996 ‘inet_addr’: Use inet_pton() or InetPton() instead or define _WINS

在VS2013以后的版本,增加了inet_pton()/InetPton()之类的新函数,用于IP地址在“点分十进制”和“二进制整数”之间转换,并且能够处理ipv4和ipv6.
而inet_addr是老函数
其实in_addr与inet_pton的联系就像是strcpy与strcoy_s的联系.微软强迫别人用她的新函数
解决办法1
1.用socket的新函数代替程序出现的所有老函数,不光是in_addr.还有gethostbyname.学习成本太高.
2.在项目属性里设置,告诉编译器,我就用老函数,让她不要报错了.
右键项目—属性—C/C++—常规—SDL检查,把是改为否
参考3
参考4

5、error C4996: ‘inet_ntoa’: Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

产生原因和解决办法参见问题4

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值