.NET Core 3.1'de bir C # Soketini kapatmanın doğru yolu nedir?
Sorun
Uygulamam için bağlantı kesilmesini halletmeye çalışıyorum ve şu ana kadar denediğim yaklaşım ne olursa olsun başarısız oldu, sunucu tarafından bağlantıyı kesmeye çalıştım, istemci tarafından bağlantıyı kesmeye çalıştım ama her iki uçta da sorunlar alıyorum, Burada başarmaya çalıştığım şey şudur bir istisna atarken kapat simgesinden kapatmak zorunda kalmadan uygulamanın bir QUIT komutuyla bağlantısını kesmek için
client.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace MessengerConsole
{
class Client
{
static string username;
static int port = 8888;
static IPAddress clientIP;
static Socket serverSocket;
static Thread processThread;
static bool connected = false;
static string GetIp()
{
Console.WriteLine("Type the server ip:");
String clientIP = Console.ReadLine();
Console.WriteLine("Client IP: " + clientIP);
//return clientIP;
//temp solution
return "192.168.0.106";
}
static void printSession()
{
Console.Clear();
Console.WriteLine("//=====================================================");
Console.WriteLine("// Session Details ");
Console.WriteLine("// =====================");
Console.WriteLine("// IP: " + clientIP + "\n// Time: " + DateTime.Now);
Console.WriteLine("//=====================================================");
}
static void clientReceiver()
{
while (true)
{
Thread.Sleep(500);
byte[] buffer = new byte[300];
int rece = serverSocket.Receive(buffer, 0, buffer.Length, 0);
Array.Resize(ref buffer, rece);
if (connected == false)
{
Console.WriteLine("[" + DateTime.Now.ToString() + "] " + Encoding.Default.GetString(buffer) + " Connected!");
connected = true;
}
else
{
if (Encoding.Default.GetString(buffer) == "QUIT")
{
//Quit
Console.WriteLine("Server Shutdown");
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
}
else
{
Console.WriteLine("[" + DateTime.Now.ToString() + "] " + Encoding.Default.GetString(buffer));
}
}
}
}
public static void StartClient()
{
processThread = new Thread(clientReceiver);
Console.WriteLine("Please enter your name");
username = Console.ReadLine();
clientIP = IPAddress.Parse(GetIp()); //Returns IP from GetIP()
Console.WriteLine("Please enter HostPort");
//string portString = Console.ReadLine();
//temp port
string portString = "80";
try
{
port = Convert.ToInt32(portString);
}
catch
{
port = 8888;
}
try
{
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Connect(new IPEndPoint(clientIP, port));
processThread.Start();
byte[] name = Encoding.Default.GetBytes(username);
//Send Name
serverSocket.Send(name);
// byte[] data = Encoding.Default.GetBytes("<" + username + "> Connected");
//serverSocket.Send(data, 0, data.Length, 0);
printSession();
while (serverSocket.Connected)
{
//byte[] sdata = Encoding.Default.GetBytes("<" + username + ">" + Console.ReadLine());
byte[] sdata = Encoding.Default.GetBytes(Console.ReadLine());
if(Encoding.Default.GetString(sdata) == "QUIT")
{
serverSocket.Send(sdata, sdata.Length, 0);
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Disconnect(true);
serverSocket.Close();
}
else
{
serverSocket.Send(sdata, 0, sdata.Length, 0);
}
}
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Message);
Console.ForegroundColor = ConsoleColor.White;
}
}
}
}
server.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace MessengerConsole
{
class Server
{
//Server Socket
static Socket serverSocket;
//Client Socket
static Socket clientSocket;
//Other Variables
static int port = 8888;
static IPAddress serverIP;
static Thread processThread;
static string username;
static bool connected = false;
//Function returns IP Address
static string GetIp()
{
//Computer Name
string hostname = Dns.GetHostName();
/*The IPHostEntry class associates a Domain Name System (DNS) host name with an array of aliases and
* an array of matching IP addresses.
*/
IPHostEntry ipentry = Dns.GetHostEntry(hostname);
//The Address
IPAddress[] ipAddress = ipentry.AddressList;
return ipAddress[ipAddress.Length - 1].ToString();
}
static void printSession()
{
Console.Clear();
Console.WriteLine("//=====================================================");
Console.WriteLine("// Session Details ");
Console.WriteLine("// =====================");
Console.WriteLine("// You are hosting the server");
Console.WriteLine("// Time: " + DateTime.Now);
Console.WriteLine("//=====================================================");
}
//Receive
static void serverReciever()
{
while (true)
{
Thread.Sleep(500);
byte[] buffer = new byte[300];
int rece = clientSocket.Receive(buffer, 0, buffer.Length, 0);
Array.Resize(ref buffer, rece);
if (connected == false)
{
Console.WriteLine("[" + DateTime.Now.ToString() + "] " + Encoding.Default.GetString(buffer) + " Connected!");
connected = true;
}
else
{
if(Encoding.Default.GetString(buffer) == "QUIT")
{
//Quit
Console.WriteLine("Client disconnected from the chat");
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
else
{
Console.WriteLine("[" + DateTime.Now.ToString() + "] " + Encoding.Default.GetString(buffer));
}
}
}
}
public static void StartServer()
{
//Thread
processThread = new Thread(serverReciever);
//Display
Console.WriteLine("Your Local Ip is " + GetIp());
Console.WriteLine("Please enter your name");
username = Console.ReadLine();
Console.WriteLine("Please enter HostPort");
// string portString = Console.ReadLine();
//temp solution
string portString = "80";
try
{
port = Convert.ToInt32(portString);
}
catch
{
port = 8888;
}
try
{
//GetIp returns string
serverIP = IPAddress.Parse(GetIp());
//TCP Socket
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(serverIP, port));
serverSocket.Listen(0);
//Server Socket listening for client requests
clientSocket = serverSocket.Accept();
printSession();
processThread.Start();
byte[] name = Encoding.Default.GetBytes(username);
clientSocket.Send(name);
while (true)
{
byte[] sdata = Encoding.Default.GetBytes(Console.ReadLine());
clientSocket.Send(sdata, 0, sdata.Length, 0);
}
}
catch
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Server already open!");
Console.ForegroundColor = ConsoleColor.White;
}
}
}
}
Bu aldığım hata
İşlenmeyen özel durum. System.ObjectDisposedException: Kullanılmış bir nesneye erişilemez. Nesne adı: 'System.Net.Sockets.Socket'. System.Net.Sockets.Socket.Receive at System.Net.Sockets.Socket.Receive (Byte [] arabelleği, Int32 ofset, Int32 boyutu, SocketFlags socketFlags) MessengerConsole.Client.clientReceiver () adresinde C: \ Users \ MessengerConsoleAppV2 \ MessengerConsole \ Client.cs: System.Threading.ThreadHelper.ThreadStart_Context (Object executionContext.RunIntext) konumunda System.Threading.ThreadHelper. , ContextCallback geri araması, Nesne durumu) --- İstisnanın atıldığı önceki konumdan yığın izlemenin sonu --- System.Threading.ExecutionContext.RunInternal'da (ExecutionContext executionContext, ContextCallback geri araması,Nesne durumu) System.Threading.ThreadHelper.ThreadStart ()
Socket.Disconnect (), Socket.Close (), Socket.Dispose () kullanmayı denedim ve hepsi aynı sonucu veriyor
DÜZENLE:
ekleyerek return
de
if(Encoding.Default.GetString(sdata) == "QUIT")
{
serverSocket.Send(sdata, sdata.Length, 0);
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
return;
}
Sunucu tarafında hiçbir hatayla sonuçlanmaz, ancak istemci yine de erişilen elden çıkarılan nesnenin istisnasını atar
İşlenmeyen özel durum. System.ObjectDisposedException: Kullanılmış bir nesneye erişilemez. Nesne adı: 'System.Net.Sockets.Socket'. System.Net.Sockets.Socket.Receive at System.Net.Sockets.Socket.Receive (Byte [] arabelleği, Int32 ofset, Int32 boyutu, SocketFlags socketFlags) MessengerConsole.Client.clientReceiver () konumunda C: \ Users \ MessengerConsoleAppV2 \ MessengerConsole \ Client.cs: System.Threading.ThreadHelper.ThreadStart_Context (Nesne durumu) System.Threading.ExecutionContext.RunIntext , ContextCallback geri araması, Nesne durumu) --- İstisnanın atıldığı önceki konumdan yığın izlemenin sonu --- System.Threading.ExecutionContext.RunInternal'da (ExecutionContext executionContext, ContextCallback geri araması,Nesne durumu) System.Threading.ThreadHelper.ThreadStart ()
Yanıtlar
QUIT
Sizinle ilgili tüm kod yerlerinde sadece soketi kapatır ve atar, ancak bu sokete hizmet veren sonsuz döngüden geri dönmez. Sanırım bu yığın bir sonraki yinelemede atılan Connected
soket üzerinde özellik değerlendirildiğinde, soketi return
kapattıktan sonra ifade eklemeyi deneyin .