我正在用C#编写一个需要处理传入连接的应用程序,之前我从未完成过服务器端编程。这引出了以下几个问题:
提前致谢。
答案 0 :(得分:19)
侦听backlog是as Pieter said,一个队列,操作系统使用该队列来存储TCP堆栈已接受但尚未由您的程序接收的连接。从概念上讲,当客户端连接它时,它会被放置在此队列中,直到您的Accept()
代码将其删除并将其交给您的程序。
因此,listen backlog是一个调整参数,可用于帮助服务器处理并发连接尝试中的峰值。请注意,这与并发连接尝试中的峰值有关,并且与服务器可以维护的最大并发连接数无关。例如,如果您的服务器每秒接收10个新连接,那么即使这些连接存在很长时间并且您的服务器支持10,000个并发连接(假设您的服务器不是最大连接数),调整侦听backlog也不会产生任何影响。 out the CPU为现有连接提供服务!)。但是,如果服务器偶尔会遇到每秒接受1000个新连接的短时间,那么您可以通过调整侦听backlog以提供更大的队列来阻止某些连接被拒绝,从而为您的服务器提供更多时间来调用{{1每个连接都有。
至于优点和缺点,优点是你可以更好地处理并发连接尝试的高峰,相应的con是操作系统需要为listen backlog队列分配更多的空间,因为它更大。所以这是一场表演与资源的交易。
就我个人而言,我可以通过配置文件进行外部调整。>
如何以及何时调用listen和accept取决于您正在使用的套接字代码的样式。使用同步代码,您可以使用值(例如10)为您的侦听待办事项调用Accept()
一次,然后循环调用Listen()
。对listen的调用设置了客户端可以连接的终点,并在概念上创建了指定大小的listen backlog队列。调用Accept()
会从侦听backlog队列中删除挂起的连接,设置一个供应用程序使用的套接字,并将其作为新建立的连接传递给您的代码。如果您的代码调用Accept()
所花费的时间,处理新连接,并且循环再次调用Accept()
比并发连接尝试之间的间隔长,那么您将开始累积条目听backlog队列。
使用异步套接字可能会有所不同,如果您使用异步接受,您将像以前一样监听一次,然后发送几个(再次可配置)异步接受。完成这些操作后,您将处理新连接并发布新的异步接受。通过这种方式,您可以使用侦听积压队列和待处理的接受“队列”,这样您就可以更快地接受连接(在线程池线程上处理异步接受的内容更多,因此您没有一个紧密的接受循环)。这通常更具可伸缩性,并为您提供两点调整以处理更多并发连接尝试。
答案 1 :(得分:3)
积压工作的作用是提供一个队列,其中包含尝试连接服务器的客户端,但尚未处理的客户端。
这涉及客户端实际连接到服务器的时间与客户Accept
或EndAccept
之间的时间。
如果接受客户端需要很长时间,那么积压可能会变满并且新的客户端连接将被拒绝,直到您有时间从队列中处理客户端为止。
关于你的问题:
我没有相关信息。如果默认数字没有任何问题(没有被拒绝的客户端连接),则将其保留为默认值。如果在新客户端想要连接时看到许多错误,请增加该数量。但是,这可能是因为您花了太多时间接受新客户。您应该在增加积压之前解决该问题;
不,这是由系统处理的。接受客户的正常机制负责这一点;
请参阅我之前的解释。
答案 2 :(得分:2)
试试这个程序,你会看到什么是积压好的。
using System;
using System.Net;
using System.Net.Sockets;
/*
This program creates TCP server socket. Then a large number of clients tries to connect it.
Server counts connected clients. The number of successfully connected clients depends on the BACKLOG_SIZE parameter.
*/
namespace BacklogTest
{
class Program
{
private const int BACKLOG_SIZE = 0; //<<< Change this to 10, 20 ... 100 and see what happens!!!!
private const int PORT = 12345;
private const int maxClients = 100;
private static Socket serverSocket;
private static int clientCounter = 0;
private static void AcceptCallback(IAsyncResult ar)
{
// Get the socket that handles the client request
Socket listener = (Socket) ar.AsyncState;
listener.EndAccept(ar);
++clientCounter;
Console.WriteLine("Connected clients count: " + clientCounter.ToString() + " of " + maxClients.ToString());
// do other some work
for (int i = 0; i < 100000; ++i)
{
}
listener.BeginAccept(AcceptCallback, listener);
}
private static void StartServer()
{
// Establish the locel endpoint for the socket
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, PORT);
// Create a TCP/IP socket
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen
serverSocket.Bind(localEndPoint);
serverSocket.Listen(BACKLOG_SIZE);
serverSocket.BeginAccept(AcceptCallback, serverSocket);
}
static void Main(string[] args)
{
StartServer();
// Clients connect to the server.
for (int i = 0; i < 100; ++i)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, PORT);
// Create a TCP/IP socket and connect to the server
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP, null, null);
}
Console.ReadKey();
}
}
}