Ich bin wirklich überfragt wie man ein TCP/UDP Client richtig schließt ohne eine Exception auszulösen.
Ich habe hier einmal den Code für den TCP Client
Spoiler anzeigen
Und hier einmal der UDP Code
Spoiler anzeigen
Nun löst der UDP Code folgende Exception aus wenn ich ihn disconnecten will
Spoiler anzeigen
System.ObjectDisposedException: Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: "System.Net.Sockets.Socket".
bei System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint)
bei System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)
bei GTAIVOnline.Network.Client.UDP.ReceiveCallback(IAsyncResult ar)
Und der TCP Code löst dies aus
Spoiler anzeigen
System.ObjectDisposedException: Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: "System.Net.Sockets.NetworkStream".
bei System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
bei GTAIVOnline.Network.Client.TCP.ReceiveCallback(IAsyncResult ar)
Beide Exceptions sind eigentlich selbsterklärend. Das Objekt ist Disposed es wird aber versucht auf dieses zuzugreifen.
Aber ich weiß trotzdem nicht wie man sie richtig disconnected. Muss ich TCP Socket/Stream in einer bestimment Reihenfolge schließen?
Meine Frage ist jetzt wie man nun TCP/UDP Client richtig disconnecten/schließen kann?
Ich möchte keine Exception beim schließen erhalten, das kommt mir so nach einem dirty weg rüber die Clients zu schließen.
Ich habe hier einmal den Code für den TCP Client
C#-Quellcode
- public class TCP {
- #region Variables
- public TcpClient socket;
- private NetworkStream stream;
- private Packet receivedData;
- private byte[] receiveBuffer;
- #endregion
- public void Connect()
- {
- socket = new TcpClient {
- ReceiveBufferSize = dataBufferSize,
- SendBufferSize = dataBufferSize
- };
- receiveBuffer = new byte[dataBufferSize];
- socket.BeginConnect(instance._iP, instance._port, ConnectCallback, socket);
- }
- public void Disconnect(bool fromError)
- {
- if (fromError) {
- instance.Disconnect(true); // Ruft diese Disconnect Methode auf nur vom einem anderen Ort
- }
- else {
- if (socket != null) {
- socket.Close();
- socket.Dispose();
- socket = null;
- }
- if (stream != null) {
- stream.Close();
- stream.Dispose();
- stream = null;
- }
- if (receivedData != null) {
- receivedData.Dispose();
- receivedData = null;
- }
- receiveBuffer = null;
- }
- }
- private void ConnectCallback(IAsyncResult ar)
- {
- try {
- socket.EndConnect(ar);
- if (!socket.Connected) {
- throw new Exception("Unknown error.");
- }
- stream = socket.GetStream();
- receivedData = new Packet();
- stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
- Main.instance.Log(string.Format("Successfully connected to {0}:{1}.", instance._iP, instance._port.ToString()), false);
- instance.IsConnected = true;
- instance.Connected?.Invoke(instance, EventArgs.Empty);
- }
- catch (Exception ex) {
- Main.instance.Log("Could not connect to server. Details: " + ex.Message, false);
- instance.CouldNotConnect?.Invoke(instance, EventArgs.Empty);
- instance.Disconnect(false);
- }
- }
- public void SendData(Packet packet)
- {
- try {
- if (socket != null) {
- if (stream != null) stream.BeginWrite(packet.ToArray(), 0, packet.Length(), null, null);
- }
- }
- catch (Exception ex) {
- Main.instance.Log(string.Format("Error sending data to server via TCP. Exception: {0}", ex.Message), false);
- }
- }
- private void ReceiveCallback(IAsyncResult ar)
- {
- try {
- if (socket != null) {
- if (stream != null) {
- if (receivedData != null) {
- int _byteLength = stream.EndRead(ar);
- if (_byteLength <= 0) {
- instance.Disconnect(true);
- return;
- }
- byte[] _data = new byte[_byteLength];
- Array.Copy(receiveBuffer, _data, _byteLength);
- receivedData.Reset(HandleData(_data));
- stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
- }
- }
- }
- }
- catch (Exception ex) {
- Main.instance.LogErrorToFile(ex, new List<string>() { @"Error in: Client\TCP\ReceiveCallback" });
- Main.instance.Log(string.Format("Error while receiving TCP data. If you manually disconnected, then ignore this error. Details: {0}", ex.Message), false); // Info
- Game.DisplayText("GTAIVOnline: Error while receiving TCP data. Check the console for details.", 5000); // Info
- instance.Disconnect(true);
- }
- }
- private bool HandleData(byte[] data)
- {
- int _packetLength = 0;
- receivedData.SetBytes(data);
- if (receivedData.UnreadLength() >= 4) {
- _packetLength = receivedData.ReadInt();
- if (_packetLength <= 0) {
- return true;
- }
- }
- while (_packetLength > 0 && _packetLength <= receivedData.UnreadLength()) {
- byte[] _packetBytes = receivedData.ReadBytes(_packetLength);
- ThreadManager.ExecuteOnMainThread(() =>
- {
- using (Packet packet = new Packet(_packetBytes)) {
- int _packetID = packet.ReadInt();
- packetHandlers[_packetID].Invoke(packet);
- }
- });
- _packetLength = 0;
- if (receivedData.UnreadLength() >= 4) {
- _packetLength = receivedData.ReadInt();
- if (_packetLength <= 0) {
- return true;
- }
- }
- }
- if (_packetLength <= 1) {
- return true;
- }
- return false;
- }
- }
Und hier einmal der UDP Code
C#-Quellcode
- public class UDP {
- #region Variables
- public UdpClient socket;
- public IPEndPoint iPEndPoint;
- #endregion
- #region Constructor
- public UDP()
- {
- iPEndPoint = new IPEndPoint(IPAddress.Parse(instance._iP), instance._port);
- }
- #endregion
- public void Connect(int localPort)
- {
- socket = new UdpClient(localPort);
- socket.Connect(iPEndPoint);
- socket.BeginReceive(ReceiveCallback, null);
- using (Packet packet = new Packet()) {
- SendData(packet);
- }
- }
- public void Disconnect(bool fromError)
- {
- if (fromError) {
- instance.Disconnect(true); // Ruft diese Disconnect Methode auf nur vom einem anderen Ort
- }
- else {
- iPEndPoint = null;
- if (socket != null) {
- socket.Close();
- socket.Dispose();
- socket = null;
- }
- }
- }
- public void SendData(Packet packet)
- {
- try {
- packet.InsertInt(instance._iD);
- if (socket != null) socket.BeginSend(packet.ToArray(), packet.Length(), null, null);
- }
- catch (Exception ex) {
- Main.instance.Log(string.Format("Error sending data to server via UDP. Exception: {0}", ex.Message), false);
- }
- }
- private void ReceiveCallback(IAsyncResult ar)
- {
- try {
- if (socket != null) {
- byte[] _data = socket.EndReceive(ar, ref iPEndPoint);
- socket.BeginReceive(ReceiveCallback, null);
- if (_data.Length < 4) {
- instance.Disconnect(true);
- return;
- }
- HandleData(_data);
- }
- }
- catch (Exception ex) {
- Main.instance.LogErrorToFile(ex, new List<string>() { @"Error in: Client\UDP\ReceiveCallback" });
- Main.instance.Log(string.Format("Error while receiving UDP data. If you manually disconnected, then you can ignore this error. Details: {0}", ex.ToString()), false); // Info
- Game.DisplayText("GTAIVOnline: Error while receiving UDP data. Check the console for details.", 5000); // Info
- Disconnect(true);
- }
- }
- private void HandleData(byte[] data)
- {
- using (Packet packet = new Packet(data)) {
- int packetLength = packet.ReadInt();
- data = packet.ReadBytes(packetLength);
- }
- ThreadManager.ExecuteOnMainThread(() => {
- using (Packet packet = new Packet(data)) {
- int packetID = packet.ReadInt();
- packetHandlers[packetID](packet);
- }
- });
- }
- }
Nun löst der UDP Code folgende Exception aus wenn ich ihn disconnecten will
System.ObjectDisposedException: Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: "System.Net.Sockets.Socket".
bei System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint)
bei System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)
bei GTAIVOnline.Network.Client.UDP.ReceiveCallback(IAsyncResult ar)
Und der TCP Code löst dies aus
System.ObjectDisposedException: Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: "System.Net.Sockets.NetworkStream".
bei System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
bei GTAIVOnline.Network.Client.TCP.ReceiveCallback(IAsyncResult ar)
Beide Exceptions sind eigentlich selbsterklärend. Das Objekt ist Disposed es wird aber versucht auf dieses zuzugreifen.
Aber ich weiß trotzdem nicht wie man sie richtig disconnected. Muss ich TCP Socket/Stream in einer bestimment Reihenfolge schließen?
Meine Frage ist jetzt wie man nun TCP/UDP Client richtig disconnecten/schließen kann?
Ich möchte keine Exception beim schließen erhalten, das kommt mir so nach einem dirty weg rüber die Clients zu schließen.
Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button
Für VB.NET Entwickler: Option Strict On nicht vergessen!
Für VB.NET Entwickler: Option Strict On nicht vergessen!