版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
好久没有写过CSDN了,正好今天没事,就把我最近写的小程序分享给大家。
废话不多说,先上图:
这个是启动WPF服务器端的界面
在没有启动Unity端的情况下点击发送消息就会提示Unity端离线
最后是成功发送消息的截图。在Unity端点击鼠标左右键或者按空格键就会发送消息到WPF端,在WPF端点击发送消息就会更新Unity中OnGUI中的消息显示。
下面讲下怎么实现的:
首先在WPF服务器端建一个F2U_Connection类,直接上代码
public class F2U_Connection
{
private static F2U_Connection _instance;
private Socket serverSocket;
private Socket clientSocket;
public static int conPort;
private Thread listenThread;
private Thread receiveThread;
private bool isListening = false;
private bool isReceiving = false;
private static byte[] result;
public msgDelegate StatusCallBack;
public msgDelegate msgCallBack;
private string _stateInfo;
private string _receiveMsg;
/// <summary>
/// 单例
/// </summary>
public static F2U_Connection Instance
{
get
{
if (F2U_Connection._instance == null)
{
F2U_Connection._instance = new F2U_Connection();
}
return F2U_Connection._instance;
}
}
public string receiveMsg
{
get
{
return this._receiveMsg;
}
set
{
this._receiveMsg = value;
msgDelegate _msgDelegate = this.msgCallBack;
if (_msgDelegate != null)
{
_msgDelegate(this._receiveMsg);
}
else
{
}
}
}
public string statusInfo
{
get
{
return this._stateInfo;
}
set
{
this._stateInfo = value;
msgDelegate statusCallBack = this.StatusCallBack;
if (statusCallBack != null)
{
statusCallBack(this._stateInfo);
}
else
{
}
}
}
static F2U_Connection()
{
F2U_Connection._instance = null;
F2U_Connection.conPort = 2019;
F2U_Connection.result = new byte[1024];
}
/// <summary>
/// 等待客户端的连接 并且创建与之通信的Socket
/// </summary>
private void listenClientConnect()
{
while (this.isListening)
{
try
{
this.clientSocket = this.serverSocket.Accept();
this.receiveThread = new Thread(new ParameterizedThreadStart(this.ReceiveU3DMsg));
this.isReceiving = true;
this.receiveThread.Start(this.clientSocket);
}
catch (Exception exception)
{
this.statusInfo = string.Concat("监听线程错误:", exception.Message);
}
}
}
public void QuitServer()
{
try
{
if (this.serverSocket != null)
{
this.serverSocket.Close();
}
if (this.clientSocket != null)
{
this.clientSocket.Close();
}
this.isListening = false;
this.listenThread.Join();
this.isReceiving = false;
this.receiveThread.Join();
}
catch (Exception exception)
{
}
}
private void ReceiveU3DMsg(object cliSocket)
{
Socket socket = (Socket)cliSocket;
while (this.isReceiving)
{
try
{
//实际接收到的有效字符
int num = socket.Receive(F2U_Connection.result);
if (num > 1)
{
this.receiveMsg = Encoding.UTF8.GetString(F2U_Connection.result, 0, num);
}
}
catch (Exception exception2)
{
Exception exception = exception2;
try
{
this.statusInfo = string.Concat("接收消息错误:", exception.Message);
this.clientSocket.Shutdown(SocketShutdown.Both);
this.clientSocket.Close();
}
catch (Exception exception1)
{
}
}
}
}
public void SendU3DMsg(string msg)
{
if ((this.clientSocket == null ? true : !this.clientSocket.Connected))
{
this.statusInfo = "Unity端离线。";
}
else
{
this.clientSocket.Send(Encoding.UTF8.GetBytes(msg));
}
}
public void StartServer()
{
//在服务端创建一个负责监听IP和端口号的Socket
IPAddress pAddress = IPAddress.Parse("127.0.0.1");
this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口号
this.serverSocket.Bind(new IPEndPoint(pAddress, F2U_Connection.conPort));
//设置监听
this.serverSocket.Listen(10);
this.statusInfo = string.Concat("启动监听:", this.serverSocket.LocalEndPoint.ToString(), "成功");
//创建监听线程
this.listenThread = new Thread(new ThreadStart(this.listenClientConnect));
this.isListening = true;
this.listenThread.Start();
}
}
msgDelegate委托需要自己声明一下,这个就是发送消息的类型:
public delegate void msgDelegate(string msg);
主窗体的后台代码也贴一下
public partial class MainWindow : Window
{
F2U_Connection F2U_Con = F2U_Connection.Instance;
public MainWindow()
{
InitializeComponent();
}
void showStatus(string msg)
{
Thread t = new Thread(new ThreadStart(delegate
{
this.Dispatcher.Invoke(new Action(delegate
{
Conn_Status.Content = msg;
}), null);
}));
t.Start();
}
void showReceiveMsg(string msg)
{
{
Thread t = new Thread(new ThreadStart(delegate
{
this.Dispatcher.Invoke(new Action(delegate
{
MSG_U2F.Content = msg;
}), null);
}));
t.Start();
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
F2U_Con.QuitServer();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
F2U_Con.StatusCallBack += showStatus;
F2U_Con.msgCallBack += showReceiveMsg;
F2U_Con.StartServer();
}
private void MSG_Send2U_Click(object sender, RoutedEventArgs e)
{
F2U_Con.SendU3DMsg(DateTime.Now.Ticks.ToString());
}
}
窗体的布局代码太简单就不贴了
然后就是Unity客户端了,这里主要是一个F2U_Connection类,直接上代码:
public partial class U2F_Connection : MonoBehaviour
{
TcpClient client;
int PortNo = 2019;
byte[] RecBuffer;
string ErrorInfo;
public static U2F_Connection Instance = null;
void Start()
{
Instance = this;
try
{
//获取Winform传过来的端口号
string[] Args = Environment.GetCommandLineArgs();
if (Args.Length > 3)
PortNo = int.Parse(Args[3]);
//连接到服务器
client = new TcpClient();
client.Connect("127.0.0.1", PortNo);
RecBuffer = new byte[client.ReceiveBufferSize];
SendWinMsg("Unity is ready");
client.GetStream().BeginRead(RecBuffer, 0, client.ReceiveBufferSize, ReceiveWinMsg, null);
}
catch (Exception) { }
}
/// <summary>
/// 发送消息给WPF
/// </summary>
/// <param name="msg"></param>
public void SendWinMsg(string msg)
{
try
{
NetworkStream ns = client.GetStream();
byte[] data = Encoding.UTF8.GetBytes(msg);
ns.Write(data, 0, data.Length);
ns.Flush();
}
catch (Exception ex)
{
ErrorInfo = ex.Message;
}
}
/// <summary>
/// 接收WPF的消息
/// </summary>
/// <param name="ar"></param>
public void ReceiveWinMsg(IAsyncResult ar)
{
try
{
//清空ErrorInfo
ErrorInfo = "";
int bytesRead = client.GetStream().EndRead(ar);
if (bytesRead < 1)
return;
else
{
_ReceivedMsg = Encoding.UTF8.GetString(RecBuffer, 0, bytesRead);
}
client.GetStream().BeginRead(RecBuffer, 0, client.ReceiveBufferSize, ReceiveWinMsg, null);
}
catch (Exception ex)
{
ErrorInfo = ex.Message;
}
}
private void OnDestroy()
{
client.Close();
}
}
接收消息使用 U2F_Connection.Instance._ReceivedMsg;
发送消息使用 U2F_Connection.Instance.SendWinMsg();
完事,收工!