我们前端是C++的,服务器是java的,传输的数据需要encode编码和decode解码。碰到的问题就是http网络请求带中文参数时(我们传的是玩家姓名),服务器接到的参数和我传过去的是不一致的。这就需要处理带中文参数的问题。
前端传过去的:content=eyJ1aWQiOiJsYWxhMTEiLCJnYW1laWQiOiIxMDAxIiwicGxheWVybmFtZSI6IumrmOWkp+Wco+iQveiQvSIsInBsYXllcnNleCI6MCwicGxheWVyaW1hZ2UiOjEwMDR9&sign=ff595ba32a2dd04d8344cf5d86788293
服务器收到的:content====eyJ1aWQiOiJsYWxhMTEiLCJnYW1laWQiOiIxMDAxIiwicGxheWVybmFtZSI6IumrmOWkp Wco iQveiQvSIsInBsYXllcnNleCI6MCwicGxheWVyaW1hZ2UiOjEwMDR9
+变成了空格。
java那边可以在传的时候加上编码格式:String encodeAfter = URLEncoder.encode(“conteng”, "utf-8");但是c++里没有这个方法。于是在网上找了一下,发现有可以支持不管带不带中文都可以的encode代码。但是这样编码之后是这样的%7B%22uid%22%3A%22lala11%22%2C%22gameid%22%3A%221001%22%2C%22channelid%22%3A%22PopStar3_360%22%7D,服务器那边说解析不了,于是我就在java上新建个测试类,代码如下:
String test = "{\"uid\":\"lala11\",\"gameid\":\"1001\",\"playername\":\"开心的笑笑\",\"playersex\":0,\"playerimage\":1005}";
System.out.println("test:"+test);
try {
String encodeAfter = URLEncoder.encode(test, "utf-8");//utf-8"
System.out.println("encodeAfter:"+encodeAfter);
String test1 = "%7B%22uid%22%3A%22lala11%22%2C%22gameid%22%3A%221001%22%2C%22channelid%22%3A%22PopStar3_360%22%7D";
String decodeAfter = URLDecoder.decode(test1, "utf-8");//utf-8"
System.out.println("test1:"+test1);
System.out.println("decodeAfter:"+decodeAfter);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
经测试通过URLEncoder.encode(test, "utf-8");//utf-8"编码后也是%7B%22uid%22%3A%22lala11%22%2C%22gameid%22%3A%221001%22%2C%22channelid%22%3A%22PopStar3_360%22%7D格式的,并且通过URLDecoder.decode(test1, "utf-8");//utf-8"解码后是完全正确的信息。
后来才发现服务器在解码的时候没用URLDecoder.decode(test1, "utf-8");//utf-8",也是醉了..
好,总结一下就是:C++用新的encode和decode代码,让服务器用URLDecoder.decode(test1, "utf-8");来解码,若需要MD5对比内容,服务器也需用URLEncoder.encode(test, "utf-8");//utf-8"来编码。
C++端的encode和decode代码如下:
.h:
#include <assert.h>
解决传输中文问题的编码///
static const char safe[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
std::string encode(const std::string &uri);
std::string decode(const std::string &uri);
.cpp:
#include <iostream>
using namespace std;
std::string encode(const std::string &uri)
{
string ret;
const unsigned char *ptr = (const unsigned char *)uri.c_str();
ret.reserve(uri.length());
for (; *ptr ; ++ptr)
{
if (!safe[*ptr])
{
char buf[5];
memset(buf, 0, 5);
#ifdef WIN32
_snprintf_s(buf, 5, "%%%X", (*ptr));
#else
snprintf(buf, 5, "%%%X", (*ptr));
#endif
ret.append(buf);
}
else if (*ptr==' ')
{
ret+='+';
}
else{
ret += *ptr;
}
}
return ret;
}
std::string decode(const std::string &uri)
{
//Note from RFC1630: "Sequences which start with a percent sign
//but are not followed by two hexadecimal characters (0-9,A-F) are reserved
//for future extension"
const unsigned char *ptr = (const unsigned char *)uri.c_str();
string ret;
ret.reserve(uri.length());
for (; *ptr; ++ptr)
{
if (*ptr == '%')
{
if (*(ptr + 1))
{
char a = *(ptr + 1);
char b = *(ptr + 2);
if (!((a >= 0x30 && a < 0x40) || (a >= 0x41 && a < 0x47))) continue;
if (!((b >= 0x30 && b < 0x40) || (b >= 0x41 && b < 0x47))) continue;
char buf[3];
buf[0] = a;
buf[1] = b;
buf[2] = 0;
ret += (char)strtoul(buf, NULL, 16);
ptr += 2;
continue;
}
}
if (*ptr=='+')
{
ret+=' ';
continue;
}
ret += *ptr;
}
return ret;
}