![](/img/trans.png)
[英]When disconnecting from WebSphere MQ with C# client TCP connections are still in CLOSE_WAIT status
[英]Unity C# ThreadAbortException when disconnecting from TCP in listener thread delegate
我正在使用 Thread 和 TCPClient 對 TCP 服務器進行讀/寫,其中客戶端 Write 初始化 TCPConnect,Read 在響應得到驗證后立即調用 TCPDisconnect。 必須這樣做以確保多個異步用戶的可用套接字(每個客戶端僅每 5-10 秒調用一次)。 但是,在處理線程時斷開連接會引發一系列錯誤。
調用 DisconnectFromTCPServer() => clientReceiveThread.Abort() 時會出現問題,在偵聽器委托 ListenForData() { using (NetworkStream ... ) { ... while ((length = stream.Read ... ) 拋出這些錯誤;
ThreadAbortException:線程被中止。 System.ComponentModel.Win32Exception..ctor (System.Int32 錯誤) (在 <1720f652f31145af877fbb9e0d1ba65c>:0) System.Net.Sockets.SocketException..ctor (System.Net.Sockets.SocketError socketError) (在 <1720f652f31145af877fbb9e0d1ba65c>:0) System.Net.Sockets.Socket.Receive(System.Byte[] 緩沖區,System.Int32 偏移量,System.Int32 大小,System.Net.Sockets.SocketFlags socketFlags)(在 <1720f652f31145af877fbb9e0d1ba65c>:0)System.Net.Sockets。 NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) (at <1720f652f31145af877fbb9e0d1ba65c>:0) Rethrow as IOException: Unable to read data from the transport connection: Thread was being aborted.. System. Net.Sockets.NetworkStream.Read(System.Byte[] 緩沖區,System.Int32 偏移量,System.Int32 大小)(在 <1720f652f31145af877fbb9e0d1ba65c>:0)
無論出於何種原因,DisconnestFromTCPServer() 中的 isAlive 標志都沒有在 ListenForData() 委托中被拾取,從而導致上述錯誤。 在從 serverMessage 引入 NewData 驗證之前,此代碼最初一直在工作,然后在從主線程調用響應時設置 = null; 當 NewData = true 時,公共移動 AIResponse()。
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 incomming stream into byte arrary.
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var incommingData = new byte[length];
Array.Copy(bytes, 0, incommingData, 0, length);
// Convert byte array to string message.
serverMessage = Encoding.UTF8.GetString(incommingData);
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() 的調用,以及關閉流和套接字,但似乎沒有什么能阻止委托嘗試讀取數據,盡管服務器響應已經記錄在控制台中並且沒有進一步的信息發送。 我不知道下一步該做什么,除非我錯過了一些非常明顯的東西。
感謝任何可以為我指明正確方向的人。
更新 - 初始問題已解決 - 見下文 - 新問題已確定
遵循第一個答案並通過一些挖掘 Thread 錯誤已得到解決(請參見下面的代碼段),但這些更改導致 SocketConnection 的行為出現了奇怪的偽影。
一旦stream.CanRead,stream.DataAvailable,stream.Close(); 循環返回頂部並返回 !serverConnection.Connected => Debug.Log("DISCONNECTED LISTEN"); 導致服務器重新連接。 此時主線程已調用 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 _incommingData = new byte[_length];
Array.Copy(bytes, 0, _incommingData, 0, _length);
serverMessage = Encoding.UTF8.GetString(_incommingData);
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);
}
}
雖然這不是一個主要問題,但在這些操作之后連接會關閉似乎很奇怪,除非我錯過了文檔中的某些內容。
再次感謝您的任何見解。
看起來您在閱讀過程中中止了。 請記住,NetworkStream.Read 僅在對方關閉時返回 0,否則將始終返回可用數據或無限期阻塞等待。
這是Stream.Read的每個合同:
在沒有數據可用的情況下,該實現將阻塞直到可以讀取至少一個字節的數據。 僅當流中沒有更多數據並且不需要更多數據時(例如關閉的套接字或文件結尾),Read 才返回 0。
我建議不要在閱讀時使用其他東西,例如 bool 'is alive' 標志。 並且在調用Read之前,調用NetworkStream.DataAvailable,否則會阻塞。
while(is_alive){
if(stream.DataAvailable){ stream.Read(...))
Thread.Sleep(100);
}
(您也可以將其移動到協程而不是線程中,並保持分配的流直到您退出,而不是一直創建/處理您需要閱讀的時間)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.