C# 套接字在传递给客户端类后断开/关闭
我正在学习套接字教程,遇到了一个问题。我有三节课;服务器、服务器客户端和客户端。服务器侦听连接请求,服务器客户端是服务器端套接字包装器,客户端是尝试连接的用户端程序 我面临的问题是,当服务器将接受的套接字传递给ServerClient类时,套接字断开连接。如果我调试传递的套接字has Connected=True,但当我在ServerClient中设置局部变量时,它将变为Connected=False 在客户端,我还没有遇到问题。我知道,套接字仍然保持连接 我做错了什么,我的代码还有什么糟糕的地方 服务器:C# 套接字在传递给客户端类后断开/关闭,c#,sockets,server,client,disconnected,C#,Sockets,Server,Client,Disconnected,我正在学习套接字教程,遇到了一个问题。我有三节课;服务器、服务器客户端和客户端。服务器侦听连接请求,服务器客户端是服务器端套接字包装器,客户端是尝试连接的用户端程序 我面临的问题是,当服务器将接受的套接字传递给ServerClient类时,套接字断开连接。如果我调试传递的套接字has Connected=True,但当我在ServerClient中设置局部变量时,它将变为Connected=False 在客户端,我还没有遇到问题。我知道,套接字仍然保持连接 我做错了什么,我的代码还有什么糟糕的地
public async void Run()
{
//
if (AcceptingClients)
{
// Error already running
return;
}
//
LoadSettings();
//
IPEndPoint localEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);
// Start The Server
_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_server.Bind(localEndPoint);
_server.Listen(100);
//
AcceptingClients = true;
//
OnServerStart(EventArgs.Empty);
// Running => Accept connections
await AcceptConnections();
// Stopped => Close connections
await CloseConnections();
// Server Stopped => Finish stuff
//
OnServerStop(EventArgs.Empty);
}
private async Task AcceptConnections()
{
await Task.Run(() =>
{
while (AcceptingClients)
{
try
{
// Set the _acceptConnectionDone to nonsignaled state.
_acceptConnectionDone.Reset();
//
_server.BeginAccept(AcceptConnectionsCallback, _server);
// Wait until a connection is made before continuing.
_acceptConnectionDone.WaitOne();
}
catch
{
//
}
}
});
}
private static void AcceptConnectionsCallback(IAsyncResult ar)
{
// Signal the AcceptConnections Task to continue.
_acceptConnectionDone.Set();
//
if (!AcceptingClients)
{
// Server Stopping or stopped
return;
}
// Get the socket that handles the client request.
Socket server = (Socket)ar.AsyncState;
Socket client = server.EndAccept(ar);
// Create the client object.
ServerClient newclient = new ServerClient(client);
// Add Events
//
_connections.TryAdd(_totalConnectionCount++, newclient);
}
服务器客户端:
private readonly Socket _connection;
//
public ServerClient(Socket s)
{
//
_connection = s;
//
Run();
// Disconnected or needs to be disconnected => Process
Disconnect();
return;
}
private async void Run()
{
//
if (_connection.Connected)
{
//
_connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
_connection.SendBufferSize = ServerExt.SendBufferSize;
_connection.NoDelay = true;
//
await ListenToClient();
}
}
客户:
public async void Connect()
{
if (_connection != null)
{
// Check if we are not connected already
}
//
LoadSettings();
//
try
{
//
IPEndPoint remoteEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);
// Create a TCP/IP socket.
_connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
ReceiveBufferSize = ServerExt.ReadBufferSize,
SendBufferSize = ServerExt.SendBufferSize,
NoDelay = true
};
// Connect to the remote endpoint.
_connection.Connect(remoteEndPoint);
//
if (_connection.Connected)
{
//
await ListenToServer();
}
}
catch
{
//
}
// Disconnected or needs to be disconnected => Process
Disconnect();
return;
}
Thnx.我通过更改ServerClient的代码来保持连接打开
public ServerClient(int id, Socket s, ClientConnectedDelegate connected, ClientDisconnectedDelegate disconnected)
{
//
Id = id;
//
_connection = s;
_disconnected = disconnected;
//
Ip = _connection.RemoteIp();
//
_connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
_connection.SendBufferSize = ServerExt.SendBufferSize;
_connection.NoDelay = true;
//
_netStream = new NetworkStream(_connection, FileAccess.ReadWrite);
//
if (_cert != null)
{
_ssl = new SslStream(_netStream, false);
_ssl.AuthenticateAsServer(_cert, false, SslProtocols.Tls, true);
//
_br = new BinaryReader(_ssl, Encoding.UTF8, false);
_bw = new BinaryWriter(_ssl, Encoding.UTF8, false);
}
else
{
_br = new BinaryReader(_netStream, Encoding.UTF8, false);
_bw = new BinaryWriter(_netStream, Encoding.UTF8, false);
}
//
Task.Factory.StartNew(ListenToClient);
//
connected(this);
}
如果没有一个好的解决方案,就不可能帮助您解决代码中的所有问题。但至于你的断开问题,它的发生是因为你正在断开插座。在
ServerClient
构造函数中要做的最后一件事是调用一些Disconnect()
方法。毫无疑问,此方法会断开或关闭套接字。这就是你的问题。不,不是这样,因为直到wait ListenToClient()之后才调用断开连接;这还没有结束。除atm外,Disconnect()是空的。“在wait ListenToClient()之后才调用Disconnect;”——是的,就是它。只要ListenToClient()
返回未完成的任务,您的Run()
方法就会返回。长时间使用构造函数块将是一个可怕的设计(因此,即使你是对的,你的代码也会被严重破坏),但你完全错误地理解了wait
的工作原理。Run()
方法在wait
完成之前返回,允许构造函数完成执行,包括调用Disconnect()
。没错,我重新测试了代码,现在我可以保持套接字连接。由于套接字被断开连接,ListenToClient()从未被触发,因此我从未接触过这一部分。无论如何,我改变了我的代码,张贴在下面。