.net 编码一个不是*的服务器&x27;每个客户端的线程数';
使用.NET时,不基于“每客户端线程数”的服务器的基本算法是什么 编辑我正在寻找一个基本的3行、4行或5行算法/psuedocode/模式来描述服务器使用的一般过程 与此相反的东西:.net 编码一个不是*的服务器&x27;每个客户端的线程数';,.net,client-server,tcp,.net,Client Server,Tcp,使用.NET时,不基于“每客户端线程数”的服务器的基本算法是什么 编辑我正在寻找一个基本的3行、4行或5行算法/psuedocode/模式来描述服务器使用的一般过程 与此相反的东西: open a server socket // this uses the port the clients know about while(running) client_socket = server_socket.listen fork(new handler_object(cl
open a server socket // this uses the port the clients know about
while(running)
client_socket = server_socket.listen
fork(new handler_object(client_socket))
线程池将允许服务器的线程数少于客户端。事件循环。等待套接字变为可写、写入、等待连接、接受它们等等。在大多数情况下,这种方法比线程更具可伸缩性,因为您通常只需要一个闭包来跟踪客户机的状态。(你当然不需要一个完整的过程,就像prefork服务器所想的那样。)用一种相当宽泛和通用的方式来描述事物(即,不特定于.net或任何其他平台),服务是以两种方式之一编程的,或者两者的组合 每个连接的线程数:正如您所注意到的,它使用单个调度实体,例如内核线程或进程,或者平台在用户空间中实现的较轻线程或协同例程,这样每个进程只需关心处理单个请求即可 伪代码示例:
function run(connection)
while(connection is open)
frobnicate(connection)
function main
listener = new Listener(port)
threads = new Collection<Thread>()
while(running)
connection = listener.accept()
threads.add(new Thread(run, connection))
join(threads)
exit()
function main
connections = new Collection<Connection>()
listener = new Listener()
connections.append(listener)
foreach connection in connections:
if connection.ready():
if connection is listener:
connections.add(connection.accept() )
else:
if connection is open:
nb_frobnicate(connection)
else:
connections.remove(connection)
yield()
if( not running )
exit()
有关此计划的说明:
- 这将创建一组单线程版本的实例,但由于它们是
由于多线程,它们必须以某种方式相互通信。这是通过使用
每个线程的
李>队列
- 还要注意,它使用了
由于与单线程程序相同的原因, 因为每个线程处理多个连接nb\u frobnate
- 工作线程池根据我们拥有的处理器数量而受到限制。
因为让更多的线程等待几乎没有什么好处 我马上就跑。实际上,要使用的最佳螺纹数可能会因 应用程序到应用程序,但cpu的数量通常是一个足够好的猜测李> - 与前面一样,主线程接受连接,并将它们传递给工作线程。
如果线程已经完成了其他线程上的工作,等待它们准备就绪,
然后,即使新的连接现在已经准备好,它也会停在那里。为了缓解这种情况,,
然后,主线程通过唤醒工作线程来通知它,从而导致阻塞
操作返回。如果这是一个正常的读取,它可能会返回一个错误
代码,但由于我们使用的是
,它只会返回一个空的ready列表 连接,线程可以再次清空其队列select()
loop {
to_read.add(client1);
to_read.add(client2);
select(to_read, timeout = 0.5);
for client in to_read { // to_read is modified by select
data = client.read
handle(data)
}
if to_read is empty {
do_bookeeping()
}
}
您可以对每个请求执行一个线程,受线程池的限制。但您可能对处理此问题的异步方法感兴趣。本页很好地介绍了异步方法的工作原理:
when [something happens] then
[create an event for something]
[put it in the queue]
此外:
此体系结构在回调AuthenticatedStream中具有很强的可扩展性在回调流中。->在回调post new BEGINDREAD中,先处理请求,然后处理流。答复
如果确实不需要,您可以取出经过身份验证的流部分(SSL或Kerberos/NTLM),然后它变成:
->在回调套接字中。->在callback post new BeginReceive中,先处理请求,然后处理套接字。答复
Ian Griffiths可以处理多个客户端,而不必为每个客户端使用线程。好的,那么算法将使用线程池,但在什么上下文中?将使用的基本算法是什么。只是寻找3、4、5行伪代码。好的,这很有意义。因此,非阻塞连接更倾向于管理对象的线程。非阻塞方法有通用算法吗?看起来很有希望。使用select是否有通用算法/伪代码/模式?很有趣。如何将其应用于套接字?@[未知]:“请求的连接”=[发生了什么事],queue.Add(new MyEvent(MyEnum.ConnectionRequested,connectionInfo))=创建事件并放入队列。对事件类型的响应可能是检查凭据(通过connectionInfo)、建立连接等。新连接可能成为其他事件的来源[请参阅另一个答案中的套接字列表轮询]@[未知]:有关所有详细信息,参见麻省理工学院的SEDA论文,你能总结一下正在使用的基本算法吗?典型的事件驱动应用程序(事件是套接字接受、读取完成和写入完成)。您没有基于堆栈的客户端状态(即线程),而是基于堆的客户端状态(即表示连接/状态的对象)?您希望避免“每个客户端线程”的哪些方面?
when [something happens] then
[create an event for something]
[put it in the queue]
while [something in queue]
if [thread is available] then
remove [thing] from queue
run [thing-response] on [available thread]
else [wait a little while]