【发布时间】:2011-01-19 02:01:47
【问题描述】:
为什么 TCP 服务器的设计大多是这样,每当它接受一个连接时,就会调用一个新进程来处理它。但是,为什么在 UDP 服务器的情况下,大多数情况下只有一个进程来处理所有客户端请求?
【问题讨论】:
标签: unix tcp network-programming udp client-server
为什么 TCP 服务器的设计大多是这样,每当它接受一个连接时,就会调用一个新进程来处理它。但是,为什么在 UDP 服务器的情况下,大多数情况下只有一个进程来处理所有客户端请求?
【问题讨论】:
标签: unix tcp network-programming udp client-server
如前所述,TCP 和 UDP 的主要区别在于 UDP 是无连接的。
使用 UDP 的程序只有一个用于接收消息的套接字。因此,如果您只是阻止并等待消息,则没有问题。
如果使用 TCP,您会为每个连接的客户端获得一个套接字。那么你不能只是阻塞并等待一个套接字接收一些东西,因为还有其他套接字必须同时处理。
所以你有两个选择,要么使用非阻塞方法,要么使用线程。当您没有一个必须处理每个客户端的 while 循环时,代码通常要简单得多,因此通常首选线程。如果使用阻塞方法,还可以节省一些 CPU 时间。
【讨论】:
select - 这允许进程阻塞,同时仍然在单个线程中处理多个 TCP 会话。高性能服务器可能会采用混合方法,例如 Apache MPMhttpd.apache.org/docs/2.0/mod/worker.html)。
当您通过 TCP 连接与客户端交谈时,您将保持 TCP 会话。因此,当建立新连接时,您需要单独的进程(或线程,无论它如何实现以及使用什么操作系统)并保持对话。但是,当您使用 UDP 连接时,您可能会收到数据报(并且您会被告知发送者的 ip 和端口),但通常情况下您无法对其做出响应。
【讨论】:
首先,经典的 Unix 服务器范例是基于过滤器的。例如,可以在 /etc/services 中配置各种网络服务,并且像 inetd 这样的程序在所有 TCP 和 UDP 套接字上侦听传入连接和数据报。当连接 / DG 到达时,它会分叉,使用 dup2 系统调用将 stdin、stdout 和 stderr 重定向到套接字,然后执行服务器进程。 You can take any program which reads from stdin and writes to stdout and turn it into a network service, such as grep.
根据 Steven 在“Unix Network Programming”中的说法,有五种服务器 I/O 模型(第 154 页):
此外,服务器可以是迭代的或并发的。
您问为什么 TCP 服务器通常是并发的,而 UDP 服务器通常是迭代的。
UDP 端更容易回答。通常 UDP 应用程序遵循一个简单的请求响应模型,其中客户端发送一个简短的请求,然后是一个回复,每一对都构成一个独立的事务。 UDP 服务器是唯一使用 Signal Drive I/O 的服务器,而且很少使用。
TCP 有点复杂。迭代服务器可以使用上面的任何 I/O 模型,除了 #4。单处理器上最快的服务器实际上是使用非阻塞 I/O 的迭代服务器。然而,这些被认为实现起来相对复杂,再加上 Unix 过滤器习惯用法,传统上使用阻塞 I/O 的并发模型的主要原因是多进程或多线程。现在,随着常见的多核系统的出现,并发模型也具有了性能优势。
【讨论】:
你的概括太笼统了。这是您可能会在基于 Unix 的服务器上看到的一种模式,其中进程创建成本很低。基于 .NET 的服务将使用线程池中的新线程,而不是创建新进程。
【讨论】:
在等待 I/O 时可以继续做有用工作的程序 通常是多线程的。进行大量计算的程序 可以整齐地分成单独的部分可以受益 多线程,如果有多个处理器。服务的程序 许多网络请求有时可以通过拥有一个 服务请求的可用线程。 GUI 程序也需要 执行计算可以从多线程中受益,因为它允许 主线程继续为 GUI 事件提供服务。
这就是我们使用 TCP 作为互联网协议的原因。
【讨论】: