Cách thích hợp để đóng C # Socket trong .NET Core 3.1 là gì?
Vấn đề
Tôi đang cố gắng xử lý ngắt kết nối cho ứng dụng của mình và bất kỳ cách tiếp cận nào tôi đã thử cho đến nay đều không thành công, tôi đã cố gắng ngắt kết nối từ phía máy chủ, tôi đã cố gắng ngắt kết nối từ phía máy khách nhưng nhận được sự cố ở cả hai đầu. Điều tôi đang cố gắng đạt được ở đây là để ngắt kết nối ứng dụng thông qua lệnh QUIT mà không cần phải đóng ứng dụng khỏi biểu tượng đóng vì nó ném ra một ngoại lệ
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;
}
}
}
}
Đây là lỗi tôi đã nhận được
Tình huống ngoại lệ không thể xử lí được. System.ObjectDisposedException: Không thể truy cập một đối tượng đã xử lý. Tên đối tượng: 'System.Net.Sockets.Socket'. tại System.Net.Sockets.Socket.Receive (Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError & errorCode) tại System.Net.Sockets.Socket.Receive (Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) tại MessengerConsole.Client.clientReceiver () trong C: \ Users \ MessengerConsoleAppV2 \ MessengerConsole \ Client.cs: dòng 42 tại System.Threading.ThreadHelper.ThreadStart_Context (Trạng thái đối tượng) tại System.Threading.ExecutionContext.RunInternal (ExecutionContext. , Lệnh gọi lại ContextCallback, Trạng thái đối tượng) --- Kết thúc theo dõi ngăn xếp từ vị trí trước đó nơi ngoại lệ được ném --- tại System.Threading.ExecutionContext.RunInternal (Lệnh thực thi ExecutionContext, Lệnh gọi lại ContextCallback,Trạng thái đối tượng) tại System.Threading.ThreadHelper.ThreadStart ()
Tôi đã thử sử dụng Socket.Disconnect (), Socket.Close (), Socket.Dispose () và tất cả chúng đều mang lại kết quả giống nhau
BIÊN TẬP:
thêm return
vào
if(Encoding.Default.GetString(sdata) == "QUIT")
{
serverSocket.Send(sdata, sdata.Length, 0);
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
return;
}
Không có lỗi ở phía máy chủ nhưng máy khách vẫn ném ngoại lệ của đối tượng đã xử lý đang được truy cập
Tình huống ngoại lệ không thể xử lí được. System.ObjectDisposedException: Không thể truy cập một đối tượng đã xử lý. Tên đối tượng: 'System.Net.Sockets.Socket'. tại System.Net.Sockets.Socket.Receive (Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError & errorCode) tại System.Net.Sockets.Socket.Receive (Byte [] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) tại MessengerConsole.Client.clientReceiver () trong C: \ Users \ MessengerConsoleAppV2 \ MessengerConsole \ Client.cs: dòng 44 tại System.Threading.ThreadHelper.ThreadStart_Context (Trạng thái đối tượng) tại System.Threading.ExecutionContext.RunInternal (ExecutionContext. , Lệnh gọi lại ContextCallback, Trạng thái đối tượng) --- Kết thúc theo dõi ngăn xếp từ vị trí trước đó nơi ngoại lệ được ném --- tại System.Threading.ExecutionContext.RunInternal (Lệnh thực thi ExecutionContext, Lệnh gọi lại ContextCallback,Trạng thái đối tượng) tại System.Threading.ThreadHelper.ThreadStart ()
Trả lời
Trong tất cả các vị trí mã liên quan đến QUIT
bạn chỉ đóng và loại bỏ ổ cắm, nhưng không quay lại từ vòng lặp vô hạn phục vụ ổ cắm này. Tôi nghĩ rằng ngăn xếp này được ném vào lần lặp tiếp theo khi thuộc Connected
tính được đánh giá trên ổ cắm được xử lý, hãy thử thêm return
câu lệnh sau khi bạn đóng ổ cắm.