私はシンプルなtcpサーバを作成しました。簡単なtcpサーバをテストすると10060(接続タイムアウト)になる
ストレステストに切り替えると問題が発生します。私たちのサーバーは多くの同時オープンソケットを処理するため、これを確認するためのストレステストが作成されています。 残念ながら、サーバが窒息しているようで、同時にオープンしているソケットの数が100個程度のときに、新しい接続要求にタイムリーに応答できません。
すでに少数のサーバを試しましたが、 。
サーバー:この記事のサンプルのようなもの(すべて同じ動作を生成)
How to write a scalable Tcp/Ip based server
ここで私たちが使用しているコードであることができます - クライアントが接続したときに - サーバーがしますだけでは、ソケットを生かし続けるためにハングアップします。
enter code here
パブリッククラスサーバー
{
private static readonly TcpListener listener = new TcpListener(IPAddress.Any, 2060);
public Server()
{
listener.Start();
Console.WriteLine("Started.");
while (true)
{
Console.WriteLine("Waiting for connection...");
var client = listener.AcceptTcpClient();
Console.WriteLine("Connected!");
// each connection has its own thread
new Thread(ServeData).Start(client);
}
}
private static void ServeData(object clientSocket)
{
Console.WriteLine("Started thread " + Thread.CurrentThread.ManagedThreadId);
var rnd = new Random();
try
{
var client = (TcpClient)clientSocket;
var stream = client.GetStream();
byte[] arr = new byte[1024];
stream.Read(arr, 0, 1024);
Thread.Sleep(int.MaxValue);
}
catch (SocketException e)
{
Console.WriteLine("Socket exception in thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, e);
}
}
}
ストレステストのクライアントは単純なTCPクライアント、そのループとオープンsoketsで、他の
class Program
{
static List<Socket> sockets;
static private void go(){
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("11.11.11.11"), 2060);
try
{
newsock.Connect(iep);
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
}
lock (sockets)
{
sockets.Add(newsock);
}
}
static void Main(string[] args)
{
sockets = new List<Socket>();
//int start = 1;// Int32.Parse(Console.ReadLine());
for (int i = 1; i < 1000; i++)
{
go();
Thread.Sleep(200);
}
Console.WriteLine("press a key");
Console.ReadKey();
}
}
}
後の1は、簡単な方法がありますこの動作を説明するには?おそらくC + +の実装は、TCPサーバーは、より良い結果を生成する場合?実際にはクライアント側の問題でしょうか?
コメントは歓迎されます!
オフェル
あなたはどのOSでテストしていますか?すべての接続に対して新しいスレッドを作成するべきではありません。一般的なスケーラビリティのために非同期インターフェイスを使用することを検討する必要があります。BeginAccept、BeginReceiveなどを参照してください。 –
win 7.私は非同期のアプローチが望ましいということを認識しています。ただし、上記の動作は、私が試したサーバー実装(コールバックを含む)で発生します。 – ofer
クライアントごとに1つのスレッドを開始しないでください。これは、実際の作業を行うよりもスケジューリングに時間がかかるため、スケーラビリティに優れていません。代わりにスレッドプールを使用してください。また、ストリームが使用されると、ストリームを閉じる必要があります(C#パターンを参照)。 –