前言:
由于最近在做一个项目,要使用到python和Unity 进行TCP通讯,这里介绍以Python端为Server,unity端为Client的例子。
Server:
服务端使用的是PyQt中的QTcpServer,用Qt的机制可以实现比较高的效率。
代码如下:
#PyQT5
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtNetwork import *
import string
import copy
class Server():
def __init__(self):
self.tcpServer = None
self.networkSession = None
self.clientNum = 0
self.strMsg = 'nihaonihaonihao'
self.shutFlag =False
def buildServer(self): #初始化Server
manager = QNetworkConfigurationManager()
if manager.capabilities() & QNetworkConfigurationManager.NetworkSessionRequired:
settings = QSettings(QSettings.UserScope, 'QtProject')
settings.beginGroup('QtNetwork')
id = settings.value('DefaultNetworkConfiguration', '')
settings.endGroup()
config = manager.configurationFromIdentifier(id)
if config.state() & QNetworkConfiguration.Discovered == 0:
config = manager.defaultConfiguration()
self.networkSession = QNetworkSession(config, self)
self.networkSession.opened.connect(self.sessionOpened)
self.statusLabel.setText("Opening network session.")
self.networkSession.open()
else:
self.sessionOpened()
self.tcpServer.newConnection.connect(self.ClientInit) #有新的client就链接到新client上进行通讯
def sessionOpened(self):#这里初始的是本机ip
if self.networkSession is not None:
config = self.networkSession.configuration()
if config.type() == QNetworkConfiguration.UserChoice:
id = self.networkSession.sessionProperty('UserChoiceConfiguration')
else:
id = config.identifier()
settings = QSettings(QSettings.UserScope, 'QtProject')
settings.beginGroup('QtNetwork')
settings.setValue('DefaultNetworkConfiguration', id)
settings.endGroup();
self.tcpServer = QTcpServer()
self.tcpServer.listen(QHostAddress.Any,50213)
if self.tcpServer.isListening() == False:
QMessageBox.critical(self, "Fortune Server",
"Unable to start the server: %s." % self.tcpServer.errorString())
self.close()
return
for ipAddress in QNetworkInterface.allAddresses():
if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0:
break
else:
ipAddress = QHostAddress(QHostAddress.LocalHost)
print(ipAddress.toString())
print(self.tcpServer.serverPort())
self.ipAddress =ipAddress.toString()
self.ipPort = self.tcpServer.serverPort()
def ClientInit(self):#有新的client就链接新的client并和其通讯
if self.clientNum ==1:
self.serverShutCurrentClient()
print("Sudden client builds the connection")
if self.clientNum==0:
print("New client builds the connection")
self.clientConnection = self.tcpServer.nextPendingConnection()
self.clientConnection.disconnected.connect(self.serverShutCurrentClient)
self.clientConnection.readyRead.connect(self.readData)
self.clientNum += 1
self.shutFlag =True
def sendData(self):#简单的发送string
if self.clientNum == 1:
block = QByteArray()
block.append(self.strMsg)
self.clientConnection.write(block)
def readData(self):#简单的读取string,并除去byte标符
tempdata = self.clientConnection.read(1024)
tempstr = str(tempdata)
tempstr = tempstr.replace("b'",'')
tempstr = tempstr.replace("'",'')
print(tempstr)
def serverShutCurrentClient(self):#client通讯断开执行
self.clientConnection.disconnectFromHost()
self.clientNum =0
print("Disconnect with the last client")
def serverShutDown(self):#Server 断开执行
if self.shutFlag :
self.clientConnection.close()
print("The Server is shut down!")
以上是比较简单的基于PyQt5的demo
Unity Client:
以下是基于C#的client类,这个demo没有使用线程,使用的是回掉函数来进行读取操作:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System;
public class TCPSocket {
#region private members
private TcpClient socketConnection;
#endregion
const int RevSize = 1024;
const int SenfSize = 1024;
public byte[] RevBuffer = new byte[RevSize];
public byte[] SendBuffer = new byte[SenfSize];
string strMesg = string.Empty;
public void TCPSocketQuit() { //断开链接
socketConnection.Close();
Debug.Log("TCP Client has quitted!");
}
public void Connect2TcpServer() { //链接初始化,同时使用回调函数
try
{
socketConnection = new TcpClient("192.168.1.103", 50213);
socketConnection.GetStream().BeginRead(RevBuffer, 0, RevSize, new AsyncCallback(Listen4Data), null);
Debug.Log("TCP Client connected!");
}
catch{
Debug.Log("Open thread for build client is error! ");
}
}
public void Listen4Data(IAsyncResult ar) {//此为回调函数
int BytesRead;
try
{
BytesRead = socketConnection.GetStream().EndRead(ar);
if (BytesRead < 1)
{
Debug.Log("Disconnected");
return;
}
strMesg = Encoding.Default.GetString(RevBuffer, 0, BytesRead );
Debug.Log(strMesg);
socketConnection.GetStream().BeginRead(RevBuffer, 0, RevSize, new AsyncCallback(Listen4Data), null);//再次使用回掉函数
}
catch {
Debug.Log("Disconnected");
}
}
public void SendMessage()//简单的发送数据
{
if (socketConnection == null)
{
return;
}
try
{
NetworkStream stream = socketConnection.GetStream();
if (stream.CanWrite)
{
string clientMessage = "This is a message from one of your clients.";
byte[] clientMessageAsByteArray = Encoding.ASCII.GetBytes(clientMessage);
stream.Write(SendBuffer, 0, 4);
}
}
catch (SocketException socketException)
{
Debug.Log("Socket exception: " + socketException);
}
}
}
以上就为通讯的两个方面,依照一定协议,就可以互相通讯数据。这里只是项目最简单的通讯部分。
由于时间原因,只做了简单的注释,有误希望指出。