C#TCP异步BeginSend回调从未发生
我正在用C#开发一个Unity游戏,并使用TCP在服务器和客户端之间交换数据 我使用异步调用来连接,这似乎很好。然后,当服务器提示客户端输入客户端版本、客户端回复、服务器询问播放器名称、播放器回复时,会发生握手/身份验证,如果一切正常,服务器会通知客户端已接受,否则连接将关闭 这在大多数情况下都有效。然而,在大约1/20的情况下,在第一个msg(服务器->客户端请求客户端版本)上,在游戏开始的几秒钟内,会调用来自第一个BeginSendnever的异步回调,从而停止身份验证过程。客户端确实会根据我的日志记录接收消息,并通过调试进行验证 服务器的调用是:C#TCP异步BeginSend回调从未发生,c#,asynchronous,tcp,callback,mono,C#,Asynchronous,Tcp,Callback,Mono,我正在用C#开发一个Unity游戏,并使用TCP在服务器和客户端之间交换数据 我使用异步调用来连接,这似乎很好。然后,当服务器提示客户端输入客户端版本、客户端回复、服务器询问播放器名称、播放器回复时,会发生握手/身份验证,如果一切正常,服务器会通知客户端已接受,否则连接将关闭 这在大多数情况下都有效。然而,在大约1/20的情况下,在第一个msg(服务器->客户端请求客户端版本)上,在游戏开始的几秒钟内,会调用来自第一个BeginSendnever的异步回调,从而停止身份验证过程。客户端确实会根据
m_isSending = true;
m_socket.BeginSend(byteArray.buffer, 0, byteArray.arrayLen, SocketFlags.None, new AsyncCallback(EndAsyncWrite), byteArray);
我添加了m_isSending,以帮助更轻松地调试/跟踪是否发送消息,以确认是否调用了回调
EndAsyncWrite为:
protected void EndAsyncWrite(IAsyncResult iar)
{
m_isSending = false;
m_socket.EndSend(iar);
ByteArray byteArray = (iar.AsyncState as ByteArray);
//Add prev msg's ByteArray to await recycling
lock (m_byteArraysAwaitingRecycle)
{
m_byteArraysAwaitingRecycle.Add(byteArray);
}
}
在这20种情况中的1种情况下,m_isSending即使在客户机接收并处理消息之后仍然为真。我已经在调试器中进行了尝试,但是由于,我假设Unity使用了mono,所以无法深入查看。但是,我在套接字的writeQ中找到了消息(我假设它是用于写入的队列)。通常它是空的,所以我想知道它是否能够解释为什么不调用回调。
. 存在的唯一条目是发送的消息和客户端接收的消息
其他信息:nagle是禁用的,blocking设置为true。其他19/20次尝试似乎工作正常,没有任何变化。我目前正在以localhost作为目标进行测试
所以我很困惑,因为我所能说的一切都做得很好。为什么回拨电话不会被呼叫?有什么想法吗?有什么建议吗?有什么办法可以解决这个问题吗?在做了更多的测试之后,我得出结论,这是在Unity Editor中运行时对线程造成的错误/影响。我是这样得出这个结论的: 我注意到,在第一次打开Unity项目并开始游戏时,问题更频繁地出现。停下来,然后再开始,通常是可行的。它总是能在2-3次尝试中起作用,并且至少还能再尝试12次左右。这当然可能表明我自己的代码中存在某种竞争条件或线程并发性问题,因此我做了以下工作:1)在Unity中创建了一个非常精简的tcplistener/tcpclient项目,消除了对byte[]数组的任何缓存/回收,或其他可能无意中影响异步或整体性能的事情。2) 我在编辑器中测试了这个新项目,并作为一个独立的构建来检查结果 当然,这需要统一性,尽管它可能很容易被采用到.net控制台应用程序中进行进一步评估。该项目由一个场景和一个游戏摄像机组成,摄像机上附有以下三个脚本。一旦连接到游戏对象,您需要将TCPClient和TCPServer引用拖放到ConnectGUI上。守则: ConnectGUI.cs
using UnityEngine;
using System.Collections;
public class ConnectGUI : MonoBehaviour {
public enum ConnectionState
{
NotConnected,
AttemptingConnect,
Connected
}
public TCPClient client;
public TCPServer server;
// Use this for initialization
void Start ()
{
client.connectState = ConnectionState.NotConnected;
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
GUI.Label(new Rect(10, 10, Screen.width - 20, 20), client.connectState.ToString());
if (client.connectState == ConnectionState.NotConnected)
{
if (GUI.Button(new Rect(Screen.width * 0.5f - 200, Screen.height * 0.5f - 40, 400, 80), "Connect"))
{
server.StartServer();
System.Threading.Thread.Sleep(10);
client.StartConnect();
}
}
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPClient : MonoBehaviour {
public ConnectGUI.ConnectionState connectState;
Socket m_clientSocket;
byte[] m_readBuffer;
void Start()
{
connectState = ConnectGUI.ConnectionState.NotConnected;
m_readBuffer = new byte[1024];
}
public void StartConnect()
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
System.IAsyncResult result = m_clientSocket.BeginConnect("127.0.0.1", 10000, EndConnect, null);
bool connectSuccess = result.AsyncWaitHandle.WaitOne(System.TimeSpan.FromSeconds(10));
if (!connectSuccess)
{
m_clientSocket.Close();
Debug.LogError(string.Format("Client unable to connect. Failed"));
}
}
catch (System.Exception ex)
{
Debug.LogError(string.Format("Client exception on beginconnect: {0}", ex.Message));
}
connectState = ConnectGUI.ConnectionState.AttemptingConnect;
}
void EndConnect(System.IAsyncResult iar)
{
m_clientSocket.EndConnect(iar);
m_clientSocket.NoDelay = true;
connectState = ConnectGUI.ConnectionState.Connected;
BeginReceiveData();
Debug.Log("Client connected");
}
void OnDestroy()
{
if (m_clientSocket != null)
{
m_clientSocket.Close();
m_clientSocket = null;
}
}
void BeginReceiveData()
{
m_clientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_clientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Client recv: '{0}'", temp));
byte[] replyMsg = new byte[m_readBuffer.Length];
System.Buffer.BlockCopy(m_readBuffer, 0, replyMsg, 0, numBytesRecv);
//Increment first byte and send it back
replyMsg[0] = (byte)((int)replyMsg[0] + 1);
SendReply(replyMsg, numBytesRecv);
}
void SendReply(byte[] msgArray, int len)
{
string temp = TCPServer.CompileBytesIntoString(msgArray, len);
Debug.Log(string.Format("Client sending: len: {1} '{0}'", temp, len));
m_clientSocket.BeginSend(msgArray, 0, len, SocketFlags.None, EndSend, msgArray);
}
void EndSend(System.IAsyncResult iar)
{
m_clientSocket.EndSend(iar);
byte[] msg = (iar.AsyncState as byte[]);
string temp = TCPServer.CompileBytesIntoString(msg, msg.Length);
Debug.Log(string.Format("Client sent: '{0}'", temp));
System.Array.Clear(msg, 0, msg.Length);
msg = null;
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPServer : MonoBehaviour
{
public enum TestMessageOrder
{
NotConnected,
Connected,
SendFirstMessage,
ReceiveFirstMessageReply,
SendSecondMessage,
ReceiveSecondMessageReply,
SendThirdMessage,
ReceiveThirdMessageReply,
Error,
Done
}
protected TcpListener m_tcpListener;
protected Socket m_testClientSocket;
protected byte[] m_readBuffer;
[SerializeField]
protected TestMessageOrder m_testClientState;
public void StartServer()
{
m_tcpListener = new TcpListener(IPAddress.Any, 10000);
m_tcpListener.Start();
StartListeningForConnections();
}
void StartListeningForConnections()
{
m_tcpListener.BeginAcceptSocket(AcceptNewSocket, m_tcpListener);
Debug.Log("SERVER ACCEPTING NEW CLIENTS");
}
void AcceptNewSocket(System.IAsyncResult iar)
{
m_testClientSocket = null;
m_testClientState = TestMessageOrder.NotConnected;
m_readBuffer = new byte[1024];
try
{
m_testClientSocket = m_tcpListener.EndAcceptSocket(iar);
}
catch (System.Exception ex)
{
//Debug.LogError(string.Format("Exception on new socket: {0}", ex.Message));
}
m_testClientSocket.NoDelay = true;
m_testClientState = TestMessageOrder.Connected;
BeginReceiveData();
SendTestData();
StartListeningForConnections();
}
void SendTestData()
{
Debug.Log(string.Format("Server: Client state: {0}", m_testClientState));
switch (m_testClientState)
{
case TestMessageOrder.Connected:
SendMessageOne();
break;
//case TestMessageOrder.SendFirstMessage:
//break;
case TestMessageOrder.ReceiveFirstMessageReply:
SendMessageTwo();
break;
//case TestMessageOrder.SendSecondMessage:
//break;
case TestMessageOrder.ReceiveSecondMessageReply:
SendMessageTwo();
break;
case TestMessageOrder.SendThirdMessage:
break;
case TestMessageOrder.ReceiveThirdMessageReply:
m_testClientState = TestMessageOrder.Done;
Debug.Log("ALL DONE");
break;
case TestMessageOrder.Done:
break;
default:
Debug.LogError("Server shouldn't be here");
break;
}
}
void SendMessageOne()
{
m_testClientState = TestMessageOrder.SendFirstMessage;
byte[] newMsg = new byte[] { 1, 100, 101, 102, 103, 104 };
SendMessage(newMsg);
}
void SendMessageTwo()
{
m_testClientState = TestMessageOrder.SendSecondMessage;
byte[] newMsg = new byte[] { 3, 100, 101, 102, 103, 104, 105, 106 };
SendMessage(newMsg);
}
void SendMessageThree()
{
m_testClientState = TestMessageOrder.SendThirdMessage;
byte[] newMsg = new byte[] { 5, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
SendMessage(newMsg);
}
void SendMessage(byte[] msg)
{
string temp = TCPServer.CompileBytesIntoString(msg);
Debug.Log(string.Format("Server sending: '{0}'", temp));
m_testClientSocket.BeginSend(msg, 0, msg.Length, SocketFlags.None, EndSend, msg);
}
void EndSend(System.IAsyncResult iar)
{
m_testClientSocket.EndSend(iar);
byte[] msgSent = (iar.AsyncState as byte[]);
string temp = CompileBytesIntoString(msgSent);
Debug.Log(string.Format("Server sent: '{0}'", temp));
}
void BeginReceiveData()
{
m_testClientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_testClientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Server recv: '{0}'", temp));
byte firstByte = m_readBuffer[0];
switch (firstByte)
{
case 1:
Debug.LogError(string.Format("Server should not receive first byte of 1"));
m_testClientState = TestMessageOrder.Error;
break;
case 2:
m_testClientState = TestMessageOrder.ReceiveSecondMessageReply;
break;
case 3:
Debug.LogError(string.Format("Server should not receive first byte of 3"));
m_testClientState = TestMessageOrder.Error;
break;
case 4:
m_testClientState = TestMessageOrder.ReceiveThirdMessageReply;
break;
case 5:
Debug.LogError(string.Format("Server should not receive first byte of 5"));
m_testClientState = TestMessageOrder.Error;
break;
default:
Debug.LogError(string.Format("Server should not receive first byte of {0}", firstByte));
m_testClientState = TestMessageOrder.Error;
break;
}
SendTestData();
}
void OnDestroy()
{
if (m_testClientSocket != null)
{
m_testClientSocket.Close();
m_testClientSocket = null;
}
if (m_tcpListener != null)
{
m_tcpListener.Stop();
m_tcpListener = null;
}
}
public static string CompileBytesIntoString(byte[] msg, int len = -1)
{
string temp = "";
int count = len;
if (count < 1)
{
count = msg.Length;
}
for (int i = 0; i < count; i++)
{
temp += string.Format("{0} ", msg[i]);
}
return temp;
}
}
TCPClient.cs
using UnityEngine;
using System.Collections;
public class ConnectGUI : MonoBehaviour {
public enum ConnectionState
{
NotConnected,
AttemptingConnect,
Connected
}
public TCPClient client;
public TCPServer server;
// Use this for initialization
void Start ()
{
client.connectState = ConnectionState.NotConnected;
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
GUI.Label(new Rect(10, 10, Screen.width - 20, 20), client.connectState.ToString());
if (client.connectState == ConnectionState.NotConnected)
{
if (GUI.Button(new Rect(Screen.width * 0.5f - 200, Screen.height * 0.5f - 40, 400, 80), "Connect"))
{
server.StartServer();
System.Threading.Thread.Sleep(10);
client.StartConnect();
}
}
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPClient : MonoBehaviour {
public ConnectGUI.ConnectionState connectState;
Socket m_clientSocket;
byte[] m_readBuffer;
void Start()
{
connectState = ConnectGUI.ConnectionState.NotConnected;
m_readBuffer = new byte[1024];
}
public void StartConnect()
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
System.IAsyncResult result = m_clientSocket.BeginConnect("127.0.0.1", 10000, EndConnect, null);
bool connectSuccess = result.AsyncWaitHandle.WaitOne(System.TimeSpan.FromSeconds(10));
if (!connectSuccess)
{
m_clientSocket.Close();
Debug.LogError(string.Format("Client unable to connect. Failed"));
}
}
catch (System.Exception ex)
{
Debug.LogError(string.Format("Client exception on beginconnect: {0}", ex.Message));
}
connectState = ConnectGUI.ConnectionState.AttemptingConnect;
}
void EndConnect(System.IAsyncResult iar)
{
m_clientSocket.EndConnect(iar);
m_clientSocket.NoDelay = true;
connectState = ConnectGUI.ConnectionState.Connected;
BeginReceiveData();
Debug.Log("Client connected");
}
void OnDestroy()
{
if (m_clientSocket != null)
{
m_clientSocket.Close();
m_clientSocket = null;
}
}
void BeginReceiveData()
{
m_clientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_clientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Client recv: '{0}'", temp));
byte[] replyMsg = new byte[m_readBuffer.Length];
System.Buffer.BlockCopy(m_readBuffer, 0, replyMsg, 0, numBytesRecv);
//Increment first byte and send it back
replyMsg[0] = (byte)((int)replyMsg[0] + 1);
SendReply(replyMsg, numBytesRecv);
}
void SendReply(byte[] msgArray, int len)
{
string temp = TCPServer.CompileBytesIntoString(msgArray, len);
Debug.Log(string.Format("Client sending: len: {1} '{0}'", temp, len));
m_clientSocket.BeginSend(msgArray, 0, len, SocketFlags.None, EndSend, msgArray);
}
void EndSend(System.IAsyncResult iar)
{
m_clientSocket.EndSend(iar);
byte[] msg = (iar.AsyncState as byte[]);
string temp = TCPServer.CompileBytesIntoString(msg, msg.Length);
Debug.Log(string.Format("Client sent: '{0}'", temp));
System.Array.Clear(msg, 0, msg.Length);
msg = null;
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPServer : MonoBehaviour
{
public enum TestMessageOrder
{
NotConnected,
Connected,
SendFirstMessage,
ReceiveFirstMessageReply,
SendSecondMessage,
ReceiveSecondMessageReply,
SendThirdMessage,
ReceiveThirdMessageReply,
Error,
Done
}
protected TcpListener m_tcpListener;
protected Socket m_testClientSocket;
protected byte[] m_readBuffer;
[SerializeField]
protected TestMessageOrder m_testClientState;
public void StartServer()
{
m_tcpListener = new TcpListener(IPAddress.Any, 10000);
m_tcpListener.Start();
StartListeningForConnections();
}
void StartListeningForConnections()
{
m_tcpListener.BeginAcceptSocket(AcceptNewSocket, m_tcpListener);
Debug.Log("SERVER ACCEPTING NEW CLIENTS");
}
void AcceptNewSocket(System.IAsyncResult iar)
{
m_testClientSocket = null;
m_testClientState = TestMessageOrder.NotConnected;
m_readBuffer = new byte[1024];
try
{
m_testClientSocket = m_tcpListener.EndAcceptSocket(iar);
}
catch (System.Exception ex)
{
//Debug.LogError(string.Format("Exception on new socket: {0}", ex.Message));
}
m_testClientSocket.NoDelay = true;
m_testClientState = TestMessageOrder.Connected;
BeginReceiveData();
SendTestData();
StartListeningForConnections();
}
void SendTestData()
{
Debug.Log(string.Format("Server: Client state: {0}", m_testClientState));
switch (m_testClientState)
{
case TestMessageOrder.Connected:
SendMessageOne();
break;
//case TestMessageOrder.SendFirstMessage:
//break;
case TestMessageOrder.ReceiveFirstMessageReply:
SendMessageTwo();
break;
//case TestMessageOrder.SendSecondMessage:
//break;
case TestMessageOrder.ReceiveSecondMessageReply:
SendMessageTwo();
break;
case TestMessageOrder.SendThirdMessage:
break;
case TestMessageOrder.ReceiveThirdMessageReply:
m_testClientState = TestMessageOrder.Done;
Debug.Log("ALL DONE");
break;
case TestMessageOrder.Done:
break;
default:
Debug.LogError("Server shouldn't be here");
break;
}
}
void SendMessageOne()
{
m_testClientState = TestMessageOrder.SendFirstMessage;
byte[] newMsg = new byte[] { 1, 100, 101, 102, 103, 104 };
SendMessage(newMsg);
}
void SendMessageTwo()
{
m_testClientState = TestMessageOrder.SendSecondMessage;
byte[] newMsg = new byte[] { 3, 100, 101, 102, 103, 104, 105, 106 };
SendMessage(newMsg);
}
void SendMessageThree()
{
m_testClientState = TestMessageOrder.SendThirdMessage;
byte[] newMsg = new byte[] { 5, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
SendMessage(newMsg);
}
void SendMessage(byte[] msg)
{
string temp = TCPServer.CompileBytesIntoString(msg);
Debug.Log(string.Format("Server sending: '{0}'", temp));
m_testClientSocket.BeginSend(msg, 0, msg.Length, SocketFlags.None, EndSend, msg);
}
void EndSend(System.IAsyncResult iar)
{
m_testClientSocket.EndSend(iar);
byte[] msgSent = (iar.AsyncState as byte[]);
string temp = CompileBytesIntoString(msgSent);
Debug.Log(string.Format("Server sent: '{0}'", temp));
}
void BeginReceiveData()
{
m_testClientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_testClientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Server recv: '{0}'", temp));
byte firstByte = m_readBuffer[0];
switch (firstByte)
{
case 1:
Debug.LogError(string.Format("Server should not receive first byte of 1"));
m_testClientState = TestMessageOrder.Error;
break;
case 2:
m_testClientState = TestMessageOrder.ReceiveSecondMessageReply;
break;
case 3:
Debug.LogError(string.Format("Server should not receive first byte of 3"));
m_testClientState = TestMessageOrder.Error;
break;
case 4:
m_testClientState = TestMessageOrder.ReceiveThirdMessageReply;
break;
case 5:
Debug.LogError(string.Format("Server should not receive first byte of 5"));
m_testClientState = TestMessageOrder.Error;
break;
default:
Debug.LogError(string.Format("Server should not receive first byte of {0}", firstByte));
m_testClientState = TestMessageOrder.Error;
break;
}
SendTestData();
}
void OnDestroy()
{
if (m_testClientSocket != null)
{
m_testClientSocket.Close();
m_testClientSocket = null;
}
if (m_tcpListener != null)
{
m_tcpListener.Stop();
m_tcpListener = null;
}
}
public static string CompileBytesIntoString(byte[] msg, int len = -1)
{
string temp = "";
int count = len;
if (count < 1)
{
count = msg.Length;
}
for (int i = 0; i < count; i++)
{
temp += string.Format("{0} ", msg[i]);
}
return temp;
}
}
TCPServer.cs
using UnityEngine;
using System.Collections;
public class ConnectGUI : MonoBehaviour {
public enum ConnectionState
{
NotConnected,
AttemptingConnect,
Connected
}
public TCPClient client;
public TCPServer server;
// Use this for initialization
void Start ()
{
client.connectState = ConnectionState.NotConnected;
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
GUI.Label(new Rect(10, 10, Screen.width - 20, 20), client.connectState.ToString());
if (client.connectState == ConnectionState.NotConnected)
{
if (GUI.Button(new Rect(Screen.width * 0.5f - 200, Screen.height * 0.5f - 40, 400, 80), "Connect"))
{
server.StartServer();
System.Threading.Thread.Sleep(10);
client.StartConnect();
}
}
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPClient : MonoBehaviour {
public ConnectGUI.ConnectionState connectState;
Socket m_clientSocket;
byte[] m_readBuffer;
void Start()
{
connectState = ConnectGUI.ConnectionState.NotConnected;
m_readBuffer = new byte[1024];
}
public void StartConnect()
{
m_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
System.IAsyncResult result = m_clientSocket.BeginConnect("127.0.0.1", 10000, EndConnect, null);
bool connectSuccess = result.AsyncWaitHandle.WaitOne(System.TimeSpan.FromSeconds(10));
if (!connectSuccess)
{
m_clientSocket.Close();
Debug.LogError(string.Format("Client unable to connect. Failed"));
}
}
catch (System.Exception ex)
{
Debug.LogError(string.Format("Client exception on beginconnect: {0}", ex.Message));
}
connectState = ConnectGUI.ConnectionState.AttemptingConnect;
}
void EndConnect(System.IAsyncResult iar)
{
m_clientSocket.EndConnect(iar);
m_clientSocket.NoDelay = true;
connectState = ConnectGUI.ConnectionState.Connected;
BeginReceiveData();
Debug.Log("Client connected");
}
void OnDestroy()
{
if (m_clientSocket != null)
{
m_clientSocket.Close();
m_clientSocket = null;
}
}
void BeginReceiveData()
{
m_clientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_clientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Client recv: '{0}'", temp));
byte[] replyMsg = new byte[m_readBuffer.Length];
System.Buffer.BlockCopy(m_readBuffer, 0, replyMsg, 0, numBytesRecv);
//Increment first byte and send it back
replyMsg[0] = (byte)((int)replyMsg[0] + 1);
SendReply(replyMsg, numBytesRecv);
}
void SendReply(byte[] msgArray, int len)
{
string temp = TCPServer.CompileBytesIntoString(msgArray, len);
Debug.Log(string.Format("Client sending: len: {1} '{0}'", temp, len));
m_clientSocket.BeginSend(msgArray, 0, len, SocketFlags.None, EndSend, msgArray);
}
void EndSend(System.IAsyncResult iar)
{
m_clientSocket.EndSend(iar);
byte[] msg = (iar.AsyncState as byte[]);
string temp = TCPServer.CompileBytesIntoString(msg, msg.Length);
Debug.Log(string.Format("Client sent: '{0}'", temp));
System.Array.Clear(msg, 0, msg.Length);
msg = null;
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
public class TCPServer : MonoBehaviour
{
public enum TestMessageOrder
{
NotConnected,
Connected,
SendFirstMessage,
ReceiveFirstMessageReply,
SendSecondMessage,
ReceiveSecondMessageReply,
SendThirdMessage,
ReceiveThirdMessageReply,
Error,
Done
}
protected TcpListener m_tcpListener;
protected Socket m_testClientSocket;
protected byte[] m_readBuffer;
[SerializeField]
protected TestMessageOrder m_testClientState;
public void StartServer()
{
m_tcpListener = new TcpListener(IPAddress.Any, 10000);
m_tcpListener.Start();
StartListeningForConnections();
}
void StartListeningForConnections()
{
m_tcpListener.BeginAcceptSocket(AcceptNewSocket, m_tcpListener);
Debug.Log("SERVER ACCEPTING NEW CLIENTS");
}
void AcceptNewSocket(System.IAsyncResult iar)
{
m_testClientSocket = null;
m_testClientState = TestMessageOrder.NotConnected;
m_readBuffer = new byte[1024];
try
{
m_testClientSocket = m_tcpListener.EndAcceptSocket(iar);
}
catch (System.Exception ex)
{
//Debug.LogError(string.Format("Exception on new socket: {0}", ex.Message));
}
m_testClientSocket.NoDelay = true;
m_testClientState = TestMessageOrder.Connected;
BeginReceiveData();
SendTestData();
StartListeningForConnections();
}
void SendTestData()
{
Debug.Log(string.Format("Server: Client state: {0}", m_testClientState));
switch (m_testClientState)
{
case TestMessageOrder.Connected:
SendMessageOne();
break;
//case TestMessageOrder.SendFirstMessage:
//break;
case TestMessageOrder.ReceiveFirstMessageReply:
SendMessageTwo();
break;
//case TestMessageOrder.SendSecondMessage:
//break;
case TestMessageOrder.ReceiveSecondMessageReply:
SendMessageTwo();
break;
case TestMessageOrder.SendThirdMessage:
break;
case TestMessageOrder.ReceiveThirdMessageReply:
m_testClientState = TestMessageOrder.Done;
Debug.Log("ALL DONE");
break;
case TestMessageOrder.Done:
break;
default:
Debug.LogError("Server shouldn't be here");
break;
}
}
void SendMessageOne()
{
m_testClientState = TestMessageOrder.SendFirstMessage;
byte[] newMsg = new byte[] { 1, 100, 101, 102, 103, 104 };
SendMessage(newMsg);
}
void SendMessageTwo()
{
m_testClientState = TestMessageOrder.SendSecondMessage;
byte[] newMsg = new byte[] { 3, 100, 101, 102, 103, 104, 105, 106 };
SendMessage(newMsg);
}
void SendMessageThree()
{
m_testClientState = TestMessageOrder.SendThirdMessage;
byte[] newMsg = new byte[] { 5, 100, 101, 102, 103, 104, 105, 106, 107, 108 };
SendMessage(newMsg);
}
void SendMessage(byte[] msg)
{
string temp = TCPServer.CompileBytesIntoString(msg);
Debug.Log(string.Format("Server sending: '{0}'", temp));
m_testClientSocket.BeginSend(msg, 0, msg.Length, SocketFlags.None, EndSend, msg);
}
void EndSend(System.IAsyncResult iar)
{
m_testClientSocket.EndSend(iar);
byte[] msgSent = (iar.AsyncState as byte[]);
string temp = CompileBytesIntoString(msgSent);
Debug.Log(string.Format("Server sent: '{0}'", temp));
}
void BeginReceiveData()
{
m_testClientSocket.BeginReceive(m_readBuffer, 0, m_readBuffer.Length, SocketFlags.None, EndReceiveData, null);
}
void EndReceiveData(System.IAsyncResult iar)
{
int numBytesReceived = m_testClientSocket.EndReceive(iar);
ProcessData(numBytesReceived);
BeginReceiveData();
}
void ProcessData(int numBytesRecv)
{
string temp = TCPServer.CompileBytesIntoString(m_readBuffer, numBytesRecv);
Debug.Log(string.Format("Server recv: '{0}'", temp));
byte firstByte = m_readBuffer[0];
switch (firstByte)
{
case 1:
Debug.LogError(string.Format("Server should not receive first byte of 1"));
m_testClientState = TestMessageOrder.Error;
break;
case 2:
m_testClientState = TestMessageOrder.ReceiveSecondMessageReply;
break;
case 3:
Debug.LogError(string.Format("Server should not receive first byte of 3"));
m_testClientState = TestMessageOrder.Error;
break;
case 4:
m_testClientState = TestMessageOrder.ReceiveThirdMessageReply;
break;
case 5:
Debug.LogError(string.Format("Server should not receive first byte of 5"));
m_testClientState = TestMessageOrder.Error;
break;
default:
Debug.LogError(string.Format("Server should not receive first byte of {0}", firstByte));
m_testClientState = TestMessageOrder.Error;
break;
}
SendTestData();
}
void OnDestroy()
{
if (m_testClientSocket != null)
{
m_testClientSocket.Close();
m_testClientSocket = null;
}
if (m_tcpListener != null)
{
m_tcpListener.Stop();
m_tcpListener = null;
}
}
public static string CompileBytesIntoString(byte[] msg, int len = -1)
{
string temp = "";
int count = len;
if (count < 1)
{
count = msg.Length;
}
for (int i = 0; i < count; i++)
{
temp += string.Format("{0} ", msg[i]);
}
return temp;
}
}
使用UnityEngine;
使用系统集合;
Net系统;
使用System.Net.Sockets;
公共类TCPServer:monobhavior
{
公共枚举TestMessageOrder
{
没有连接,
有联系的,
发送第一条消息,
收到第一封邮件回复,
发送第二条消息,
收到第二封邮件回复,
发送第三条消息,
收到第三封邮件,
错误,
多恩
}
受保护的TcpListener m_TcpListener;
受保护的套接字m_testClientSocket;
受保护字节[]m_readBuffer;
[序列化字段]
受保护的TestMessageOrder m_testClientState;
public void StartServer()
{
m_tcpListener=新的tcpListener(IPAddress.Any,10000);
m_tcpListener.Start();
StartListeningForConnections();
}
void statistingforconnections()
{
m_tcpListener.beginacepceptsocket(AcceptNewSocket,m_tcpListener);
Log(“接受新客户端的服务器”);
}
void AcceptNewSocket(System.IAsyncResult iar)
{
m_testClientSocket=null;
m_testClientState=TestMessageOrder.NotConnected;
m_readBuffer=新字节[1024];
尝试
{
m_testClientSocket=m_tcpListener.EndAcceptSocket(iar);
}
catch(System.Exception-ex)
{
//LogError(string.Format(“新套接字上的异常:{0}”,ex.Message));
}
m_testClientSocket.NoDelay=true;
m_testClientState=TestMessageOrder.Connected;
BeginReceiveData();
SendTestData();
StartListeningForConnections();
}
void SendTestData()
{
Log(string.Format(“服务器:客户端状态:{0}”,m_testClientState));
开关(m_testClientState)
{
案例TestMessageOrder。已连接:
SendMessageOne();
打破
//案例TestMessageOrder.SendFirstMessage:
//中断;
案例TestMessageOrder.ReceiveFirstMessageReply:
SendMessageTwo();
打破
//案例TestMessageOrder.SendSecondMessage:
//中断;
案例TestMessageOrder.ReceiveSecondMessageReply:
SendMessageTwo();
打破
案例TestMessageOrder.SendThirdMessage:
打破
案例TestMessageOrder.ReceiveThirdMessageReply:
m_testClientState=TestMessageOrder.Done;
Debug.Log(“全部完成”);
打破
案例TestMessageOrder。完成:
打破
违约:
LogError(“服务器不应该在这里”);
打破
}
}
void SendMessageOne()
{
m_testClientState=TestMessageOrder.SendFirstMessage;
byte[]newMsg=新字节[]{1100、101、102、103、104};
发送消息(newMsg);
}
void sendmagestwo()
{
m_testClientState=TestMessageOrder.SendSecondMessage;
byte[]newMsg=新字节[]{3,100,101,102,103,104,105,106};
s