【发布时间】:2020-05-29 18:29:07
【问题描述】:
所以,我已经解决了我遇到的问题。这与我是否在 C# 客户端的 StreamWriter 上使用编码有关,但我想知道如何处理这些额外的 3 个字节。
这是一个用 C# 编写的客户端和一个用 Go 编写的服务器。 为什么选择 C#? 稍后它将为云应用提供 Unity 应用程序。 为什么要去?我只是想用它。我的服务器也是 Linux 并且 Go 很容易 x 编译。
问题是从我的 C# 客户端发送的数据在前面附加了 3 个额外的字节,这与 Go 的 Json.Unmarshal 函数在数据到达服务器后直接输入它发生冲突。
这是离开 C# 客户端的 JSON 格式字符串{"channel":0, "data": {"name":"Hasty Wombat","uuid":"e91ccc23-7e80-4189-958e-9b778dce1146","type":"Drone"}}\n
这是在 C# 客户端通过配置了 UTF8 的流写入器之前的字节数组。_sWriter = new StreamWriter(_tStream, System.Text.Encoding.UTF8, 8192);
长度:108
123 34 99 104 97 110 110 101 108 34 58 48 44 32 34 100 97 116 97 34 58 32 123 34 110 97 109 101 34 58 34 72 97 115 116 121 32 87 111 109 98 97 116 34 44 34 117 117 105 100 34 58 34 101 57 49 99 99 99 50 51 45 55 101 56 48 45 52 49 56 57 45 57 53 56 101 45 57 98 55 55 56 100 99 101 49 49 52 54 34 44 34 116 121 112 101 34 58 34 68 114 111 110 101 34 125 125 10
当它到达我的 Go 服务器时,它看起来像这样:
长度:111
[239 187 191 123 34 99 104 97 110 110 101 108 34 58 48 44 32 34 100 97 116 97 34 58 32 123 34 110 97 109 101 34 58 34 72 97 115 116 121 32 87 111 109 98 97 116 34 44 34 117 117 105 100 34 58 34 50 99 57 49 48 97 99 98 45 53 101 101 102 45 52 98 56 101 45 56 52 50 54 45 54 49 102 100 100 99 99 51 101 51 55 100 34 44 34 116 121 112 101 34 58 34 68 114 111 110 101 34 125 125 10]
根据我的快速研究,前面添加的 3 个额外字节与 UTF8 的字节顺序有关。这很好,但它干扰了我将这个 JSON 字节数组解组为地图的能力。
func handleRequest (conn net.Conn) {
for {
data, err := bufio.NewReader(conn).ReadBytes('\n');
if err != nil {
fmt.Println("Client disconnect")
conn.Close()
return
}
var mappedData map[string]interface{}
err = json.Unmarshal(data, &mappedData)
if err != nil {
fmt.Println("err:", err)
continue
}
// ...
}
}
err: invalid character 'ï' looking for beginning of value
Go 中的 Json.Unmarshal 函数不喜欢那个字节数组。起初我的解决方法是只切掉前 3 个字节。但是,当我开始添加 TCP 输出未添加这 3 个字节的 Go 客户端时,这会导致问题。
显而易见的解决方法是不要在 C# 客户端上的 StreamWriter 中使用 UTF8。
// NetworkManager.cs
_tcpconn = new TCPConnection(_ipAddress, _port, OnConnectionFailure);
if (_tcpconn.SetupSocket()) {
var data = "{\"channel\":0, \"data\": {" +
"\"name\":" + "\"" + _clientName + "\"," +
"\"uuid\":" + "\"" + _uuid + "\"," +
"\"type\":" + "\"Drone\"" +
"}}" + "\n";
_tcpconn.WriteSocket(data);
// TCPConnection.cs
public bool SetupSocket () {
try {
_socket = new TcpClient(_conHost, _conPort);
_tStream = _socket.GetStream();
// _sWriter = new StreamWriter(_tStream, System.Text.Encoding.UTF8, 8192);
_sWriter = new StreamWriter(_tStream); // Fixed my problem
_sReader = new StreamReader(_tStream);
}
catch (Exception e) {
throw new Exception("Socket error:" + e.Message);
return false;
}
_socketReady = true;
return true;
}
public void WriteSocket (string theLine) {
if (!_socketReady)
return;
try {
_sWriter.Write(theLine);
_sWriter.Flush();
}
catch {
_socketReady = false;
_onConnectionFailure();
}
}
现在我想知道 Go 是否有能够正确解码 UTF8 字节数组的东西,或者能够正确检测这些额外字节(或任何额外的编码字节)的东西,并给我 Json.Unmarshal 函数想要的原始 JSON。我正在尝试将我的 Stream Writer 设置为多功能,但我不确定我是否需要编码 UTF8 的东西或有什么优势。
【问题讨论】:
-
Go 默认原生处理 utf8,json 必须是 utf8 编码。问题是 json 不能有 BOM tools.ietf.org/html/rfc8259#section-8.1
-
如果你 initialize the
StreamWriter没有指定编码,编码将被设置为默认的 UTF-8 但没有字节顺序标记(8192 也是默认的缓冲区网络流)