做实验室的项目,使用socket在python和unity之间传输json数据,遇到了不少坑。
python程序之间以及C#程序之间的socket通信
先讲讲两个python之间的socket通信,不得不赞叹python写代码简直舒服,估计以后写代码会经常拿python先试试水比较思路,有大致模型后再考虑转其他语言编码
比较需要注意的是,在不同语言的程序之间进行socket通信,编码需要同时设置为UTF-8或者其他,否者将会出现乱码
python程序和C#程序的socket传输json
先码上
import socket
import threading
import json
sendData = {
"infolist":
[
{
"name": "fefa",
"age": "34"
},
{
"name": "hrg",
"age": "21
}
]
}
# 当新的客户端连入时会调用这个方法
def on_new_connection(client_executor, addr):
print('Accept new connection from %s:%s...' % addr)
# 发送一个信息
#while(True):
client_executor.send(bytes(repr(json.dumps(sendData)).encode('utf-8'))) #发送json信息
client_executor.close()
print('Connection from %s:%s closed.' % addr)
# 构建Socket实例、设置端口号 和监听队列大小
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.bind(('127.0.0.1', 10086))
listener.listen(5)
print('Waiting for connect...')
# 进入死循环,等待新的客户端连入。一旦有客户端连入,就分配一个线程去做专门处理。然后自己继续等待。
while True:
client_executor, addr = listener.accept()
t = threading.Thread(target=on_new_connection, args=(client_executor, addr))
t.start()
通过python发送json信息,首先需要使用json.dumps将dict格式转化为str格式,但socket仅支持发送byte序列,因而还需要将str序列化,也就是repr()函数,再一个编码完成即可
而对应于unity端的C# socket接收,使用Unity工具集的jsonUtility进行json解析
using Assets.Scripts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using UnityEngine;
public class getSocket : MonoBehaviour
{
private TextMesh text;
private string message;
private Socket client;
private string host = "127.0.0.1";
private int port = 10086;
private byte[] messTmp;
// Use this for initialization
void Start()
{
text = GameObject.FindGameObjectWithTag("text").GetComponent<TextMesh>();
messTmp = new byte[1024];
// 构建一个Socket实例,并连接指定的服务端。这里需要使用IPEndPoint类(ip和端口号的封装)
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
client.Connect(new IPEndPoint(IPAddress.Parse(host), port));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return;
}
//client.Close();
}
Data ReadToObject(string json)
{
Data deserializedUser = new Data();
deserializedUser = (Data)JsonUtility.FromJson(json, deserializedUser.GetType());
return deserializedUser;
}
void GetMessage()
{
var count = client.Receive(messTmp);
if (count != 0)
{
Data frame = ReadToObject(Encoding.UTF8.GetString(messTmp, 1, count - 2));
message = frame.ToString();
Array.Clear(messTmp, 0, count);
}
}
void FixedUpdate()
{
GetMessage();
text.text = message;
}
}
Data.cs
[Serializable]
class Data
{
public List<Frame> infolist;
public override string ToString()
{
string tmp = "";
foreach(Frame one in infolist)
{
tmp += one+"\n";
}
return tmp;
}
}
Frame.cs
[Serializable]
class Frame
{
public string name;
public string age;
public override string ToString()
{
return "name: " + name + " age: " + age;
}
}
unity端需要注意几点:
1.jsonUtility存在一些局限性(这是个大坑)。
好比如以上代码,如果python传输过来的数据直接是
{
"name": "fefa",
"age": "34"
}
或者
[
{
"name": "fefa",
"age": "34"
},
{
"name": "hrg",
"age": "21"
}
]
并直接进行解析赋予对象,将导致解析失败
2.对于被序列化的对象,必须加上[Serializable]
3.经过python的json.dumps过来后的数据不可以直接在C#进行解析!如下图
3.JPG
注意蓝色一行,(测试用),从socket刚刚接收过来的数据,解析为str后,也就是字符串haha,里面竟然有“‘”,这里没办法解析,需要去除,否则报错,所以在传入ReadToObjec()函数里面的string是去除了“’”的字符串
稍触皮毛,有深入会改进
参考:
http://blog.csdn.net/yy763496668/article/details/77875195
https://www.jianshu.com/p/269826e9e06e
网友评论