gpt4 book ai didi

c# - 限制连接的数量和时间 TcpListener。如何正确close\stop TcpListener 和TcpClient?

转载 作者:行者123 更新时间:2023-11-30 16:13:23 26 4
gpt4 key购买 nike

我有一些代码:

    protected TcpListener ClientListener;
protected TcpClient ClientSocket;
protected Thread th1;
public static string server_ip = string.Empty;
public static string server_port = string.Empty;

internal void start_potok()
{
Protection.Ban.ban_del();
th1 = new Thread(start_listener);
th1.IsBackground = true;
th1.Start();
}

internal void stop_potok()
{
th1.Abort();
if (ClientSocket != null)
{
ClientSocket.Close();
}
ClientListener.Stop();
}

private void start_listener()
{
try
{
ClientListener = new TcpListener(IPAddress.Parse(server_ip), Convert.ToInt32(server_port));
ClientListener.Start();
ClientSocket = default(TcpClient);
while (true)
{
ClientSocket = ClientListener.AcceptTcpClient();
client_connected(ClientSocket);
}
catch (ThreadAbortException ex)
{
//not catch this exception
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}

private void client_connected(TcpClient client)
{
//check bans and other
LoginClientProc lcp = new LoginClientProc(client);
}

听力等级:

class LoginClientProc
{
internal EndPoint address;
internal TcpClient client;
internal NetworkStream stream;
private byte[] buffer;

internal LoginClientProc(TcpClient Client)
{
address = Client.Client.RemoteEndPoint;
client = Client;
stream = Client.GetStream();

new System.Threading.Thread(read).Start();
}

void read()
{
try
{
buffer = new byte[2];
stream.BeginRead(buffer, 0, 2, new AsyncCallback(OnReceiveCallbackStatic), null);
}
catch (Exception ex)
{
throw ex;
}
}

private void OnReceiveCallbackStatic(IAsyncResult result)
{
int rs = 0;
try
{
rs = stream.EndRead(result);

if (rs > 0)
{
short Length = BitConverter.ToInt16(buffer, 0);
buffer = new byte[Length - 2];
stream.BeginRead(buffer, 0, Length - 2, new AsyncCallback(OnReceiveCallback), result.AsyncState);
}
else
//0 = client close connection
}
catch (Exception s)
{
}
}

private void OnReceiveCallback(IAsyncResult result)
{
stream.EndRead(result);

byte[] buff = new byte[buffer.Length];
buffer.CopyTo(buff, 0);
if (!verify_packet)
{
//Exception
}
else
{
handle(buff);
new System.Threading.Thread(read).Start();
}
}

private void handle(byte[] buff)
{
byte id = buff[0];
switch (id)
{
//cases for headers packets
default:
//unknown packet
//Here need correct Close connection
break;
}
//response for packet
}

所以,我有一些问题:

  1. 如何限制客户端连接数? (不超过10用户,例如)
  2. 如何限制客户端连接的时间(生命周期)? (例如不超过 30 秒)
  3. 如何在应用程序关闭时正确停止监听线程(TcpListener、TcpClient)?
  4. 当Server收到未知数​​据包时如何正确关闭TcpClient?

感谢您的回答!

最佳答案

您可能需要使用队列。这是服务器端可能的解决方案的草图:

class Program
{
Queue<Connection> queue = new Queue<Connection>();

TcpListener listener;

ManualResetEvent reset = new ManualResetEvent(true);

static void Main(string[] args)
{
new Program().Start();
}

void Start()
{
new Thread(new ThreadStart(HandleConnection)).Start();

while (true)
{
while (queue.Any())
{
var connection = queue.Dequeue();

connection.DoStuff();

if(!connection.Finished)
queue.Enqueue(connection);
}

reset.WaitOne();
}
}

static readonly byte[] CONNECTION_REFUSED = Encoding.ASCII.GetBytes("Cannot accept a connection right now.");
static readonly int CONNECTION_REFUSED_LENGTH = CONNECTION_REFUSED.Length;

void HandleConnection()
{
listener.Start();

while (true)
{
var client = listener.AcceptTcpClient();

if (queue.Count <= 10)
{
queue.Enqueue(new Connection(client));
reset.Set();
}
else
{
client.GetStream().Write(CONNECTION_REFUSED, 0, CONNECTION_REFUSED_LENGTH);
client.Close();
}
}
}

}

public sealed class Connection
{
readonly TcpClient client;
readonly Stopwatch stopwatch = new Stopwatch();

public Connection(TcpClient client)
{
this.client = client;
stopwatch.Start();
}

public void DoStuff()
{

}

public void Abort()
{
//You can write out an abort message to the client if you like.
client.Close();
completed = true;
}

bool completed;

public bool Finished
{
get
{
return stopwatch.ElapsedMilliseconds > 30 * 1000 || completed;
}
}
}

基本思想是使用一个线程将传入连接添加到队列中,然后使用另一个线程遍历队列以处理每个连接。当连接 Finished 时,连接将从队列中删除(或者更确切地说不重新排队)。

一个健壮的解决方案可能需要使用 lock 语句或 ConcurrentQueue 类。在我的草图中,为了简洁起见,我在 TCPClient 类上使用了阻塞方法,但是,当然您会希望使用非阻塞方法。

关于c# - 限制连接的数量和时间 TcpListener。如何正确close\stop TcpListener 和TcpClient?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21783422/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com