我使用线程和TCPClient对TCP服务器进行读/写,其中客户端写初始化TCPConnect,并在响应验证后立即调用TCPDisconnect。必须这样做,以确保多个异步用户可用的套接字(每个客户端仅每5-10秒调用一次)。但是,当处理线程时,断开将引发一系列错误。
当调用DisconnectFromTCPServer() => clientReceiveThread.Abort()时,在侦听器委托ListenForData() { The (NetworkStream .){.时间(长度= stream.Read .)抛出这些错误;
ThreadAbortException:线程被中止。System.ComponentModel.Win32Exception..ctor (System.Int32 error) (at <1720f652f31145af877fbb9e0d1ba65c>:0) System.Net.Sockets.SocketException..ctor (System.Net.Sockets.SocketError socketError) (at <1720f652f31145af877fbb9e0d1ba65c>:0) System.Net.Sockets.Socket.Receive (System.Byte[]缓冲区,System.Int32偏移量,System.Int32大小,System.Net.Sockets.SocketFlags socketFlags) (at <1720f652f31145af877fbb9e0d1ba65c>:0) System.Net.Sockets.NetworkStream.Read (System.Byte[]缓冲器,System.Int32偏移量,System.Int32大小)(在<1720f652f31145af877fbb9e0d1ba65c>:0)重新抛出为IOException:无法从传输连接读取数据:线程被中止。System.Net.Sockets.NetworkStream.Read (System.Byte[]缓冲器,System.Int32偏移量,System.Int32大小) (at <1720f652f31145af877fbb9e0d1ba65c>:0)
出于任何原因,isAlive ()中的DisconnestFromTCPServer()标志没有在ListenForData()委托中被选中,从而导致上述错误。在从主线程调用响应时,当从NewData = true调用响应时,这段代码最初是在从serverMessage中引入对NewData的验证之前,然后设置= null。
private void ConnectToTcpServer()
{
try
{
Debug.Log("CONNECTING TO SERVER...");
clientReceiveThread = new Thread(new ThreadStart(ListenForData));
clientReceiveThread.IsBackground = true;
clientReceiveThread.Start();
isAlive = true;
}
catch (Exception e)
{
Debug.Log("On client connect exception " + e);
}
}
private void DisconnectFromTcpServer()
{
isAlive = false;
if (socketConnection.Connected) ((IDisposable)socketConnection).Dispose();
StartCoroutine(ServerDisconnectedCoroutine(() => !socketConnection.Connected));
if (clientReceiveThread.IsAlive) clientReceiveThread.Abort();
clientReceiveThread.Join();
ServerConnected = false;
}
private IEnumerator ServerDisconnectedCoroutine(System.Func<bool> socketDisconnected)
{
yield return new WaitUntil(socketDisconnected);
}
public void ListenForData()
{
// SWITCH PORTS ON EACH CONNECT - BALANCE THE LOAD
// WRAP IN COUNTER
port = port == 12345 ? 12344 : 12345;
try
{
socketConnection = new TcpClient("65.21.xxx.xxx", 12345);
Byte[] bytes = new Byte[1024];
Thread.Sleep(100);
while (isAlive)
{
// Test socket connection
if (!socketConnection.Connected)
{
Debug.Log("DISCONNECTED LISTEN");
serverTimeout();
return;
}
else
ServerConnected = true;
// Get a stream object for reading
using (NetworkStream stream = socketConnection.GetStream())
{
int length;
// Read incoming stream into byte arrary.
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var incomingData = new byte[length];
Array.Copy(bytes, 0, incomingData, 0, length);
// Convert byte array to string message.
serverMessage = Encoding.UTF8.GetString(incomingData);
Debug.Log("server message received as: " + serverMessage);
// ORIGINAL NewData = true;
}
stream.Close();
}
}
}
catch (SocketException socketException)
{
Debug.Log("Socket exception: " + socketException);
}
catch (ThreadAbortException threadException)
{
Debug.Log("ThradException: " + threadException);
}
}
public bool IfNewData()
{
if (serverMessage != null && !NewData) aiDataFromServer.LoadString(serverMessage);
if (aiDataFromServer.type != "Error") NewData = true;
return NewData;
}
public Move AIResponse()
{
NewData = false;
// ORIGINAL - serverMessage ! set to null
serverMessage = null;
DisconnectFromTcpServer();
return aiDataFromServer.moveData;
}
我尝试过各种方法来延迟对Thread.Abort()的调用,以及关闭流和套接字,但是似乎没有什么能阻止委托尝试读取数据,尽管服务器响应已经记录在控制台中,并且没有发送进一步的信息。我对下一步该做什么有点不知所措,除非我错过了一些显而易见的事情。
感谢任何能为我指明正确方向的人。
更新-初始问题已解决-见下文-新问题已确定
按照第一个答案,并对线程错误进行了一些挖掘,已经解决了线程错误(请参阅下面的片段),但是这些更改在SocketConnection的行为中造成了一个奇怪的伪影。
一旦stream.CanRead,stream.DataAvailable,stream.Close();循环返回到top并返回!serverConnection.Connected => Debug.Log(“断开连接侦听”);导致服务器重新连接。此时主线程调用了AIResponse(),连接和线程无论如何都被关闭了,但是我无法确定为什么在读取流之后关闭socketConnection。
public void ListenForData()
{
// SWITCH PORTS ON EACH CONNECT - BALANCE THE LOAD
// WRAP IN COUNTER
port = port == 12345 ? 12344 : 12345;
try
{
socketConnection = new TcpClient("65.21.xxx.xxx", 12345);
Byte[] bytes = new Byte[1024];
while (isAlive)
{
Debug.Log("IS ALIVE");
// Test socket connection
if (!socketConnection.Connected && connectionRequired)
{
Debug.Log("DISCONNECTED LISTEN");
serverTimeout();
return;
}
else
ServerConnected = true;
using (NetworkStream stream = socketConnection.GetStream())
{
if (stream.CanRead)
{
int _length;
do
{
_length = stream.Read(bytes, 0, bytes.Length);
var _incomingData = new byte[_length];
Array.Copy(bytes, 0, _incomingData, 0, _length);
serverMessage = Encoding.UTF8.GetString(_incomingData);
Debug.Log("server message received as: " + serverMessage);
// ALLOW REFERENCES TO BE UPDATED
if (!stream.DataAvailable)
Thread.Sleep(1);
}
while (stream.DataAvailable);
}
stream.Close();
Debug.Log("STREAM CLOSED");
}
}
}
catch (SocketException socketException)
{
Debug.Log("Socket exception: " + socketException);
}
catch (ThreadAbortException threadException)
{
Debug.Log("ThradException: " + threadException);
}
}
虽然这不是一个主要的问题,但在这些操作之后,连接被关闭似乎是非常奇怪的,除非我错过了文档中的一些内容。
再次感谢您的洞察力。
发布于 2022-07-11 17:24:18
看上去你在阅读过程中失败了。请记住,只有当另一方关闭时,NetworkStream.Read才会返回0,否则始终会返回可获取的数据或无限期地等待。
这是Stream.Read的合同
如果没有可用的数据,实现将阻塞,直到至少可以读取一个字节的数据。只有当流中没有更多的数据并且不需要更多的数据(例如关闭的套接字或文件结束时),Read才返回0。
我建议你不要大声呼喊你的读物,而不是其他的东西,比如“是活的”旗子。在调用Read之前,调用NetworkStream.DataAvailable,否则将阻塞。
while(is_alive){
if(stream.DataAvailable){ stream.Read(...))
Thread.Sleep(100);
}
(您也可以将它移动到协同线而不是线程,并将流分配到退出,而不是创建/处理所有需要读取的时间)
https://stackoverflow.com/questions/72940509
复制相似问题