ホームページ >バックエンド開発 >C++ >長時間実行される接続を備えたスケーラブルな TCP/IP サーバーを設計するにはどうすればよいですか?

長時間実行される接続を備えたスケーラブルな TCP/IP サーバーを設計するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-29 05:06:09378ブラウズ

How to Design a Scalable TCP/IP Server with Long-Running Connections?

スケーラブルな TCP/IP サーバーの設計パターン

長時間実行される接続を必要とするスケーラブルな TCP/IP サーバーを設計する場合、考慮することが重要です最も効率的なネットワーク アーキテクチャ。非同期ソケットは、過剰なリソースを消費せずに複数のクライアントを同時に処理できるため、推奨されるアプローチです。

ネットワーク アーキテクチャ

  • サーバー:

    • 少なくとも次の条件でサービスを開始します受信接続を処理する 1 つのスレッド。
    • BeginReceive メソッドと EndReceive メソッドを使用して非同期ソケットを実装します。
    • アクティブなクライアントへの参照を保持するリストを含む、クライアント接続を管理するクラスを作成します。
    • サーバーソケットで BeginAccept メソッドを使用して受信接続をリッスンし、接続が確立されたら AcceptCallback を呼び出します。
  • クライアント:

    • ソケットを使用してサーバーに接続します。
    • 送信およびBeginSend を使用してソケット経由で非同期にデータを受信し、 BeginReceive.

データ フロー

  • データは主にサーバーからクライアントに流れ、クライアントからのコマンドも時折流れます。 .
  • サーバーはステータス データを定期的に
  • クライアントから受信したデータはバッファリングして非同期に処理でき、スレッド プール上にジョブを作成して、さらなるデータ受信の遅延を防ぎます。

コード例

using System;
using System.Net;
using System.Net.Sockets;

namespace TcpServer
{
    class xConnection
    {
        public byte[] buffer;
        public System.Net.Sockets.Socket socket;
    }

    class Server
    {
        private List<xConnection> _sockets;
        private System.Net.Sockets.Socket _serverSocket;
        private int _port;
        private int _backlog;

        public bool Start()
        {
            IPHostEntry localhost = Dns.GetHostEntry(Dns.GetHostName());
            IPEndPoint serverEndPoint = new IPEndPoint(localhost.AddressList[0], _port);

            try
            {
                _serverSocket = new Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                _serverSocket.Bind(serverEndPoint);
                _serverSocket.Listen(_backlog);
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket);
                return true;
            }
            catch (Exception e)
            {
                // Handle exceptions appropriately
                return false;
            }
        }

        private void AcceptCallback(IAsyncResult result)
        {
            try
            {
                Socket serverSocket = (Socket)result.AsyncState;
                xConnection conn = new xConnection();
                conn.socket = serverSocket.EndAccept(result);
                conn.buffer = new byte[_bufferSize];

                lock (_sockets)
                {
                    _sockets.Add(conn);
                }
                conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket);
            }
            catch (Exception e)
            {
                // Handle exceptions appropriately
            }
        }

        private void Send(byte[] message, xConnection conn)
        {
            if (conn != null &amp;&amp; conn.socket.Connected)
            {
                lock (conn.socket)
                {
                    conn.socket.Send(message, message.Length, SocketFlags.None);
                }
            }
        }
    }
}

追加考慮事項

  • 受信データ フラグメントの処理には再アセンブリ プロトコルの使用を検討してください。
  • 潜在的なバグを避けるために、一度に 1 つの BeginAccept を使用してください。
  • 同期スレッドの安全性を確保するために、クライアント リストなどの共有リソースにアクセスします。

以上が長時間実行される接続を備えたスケーラブルな TCP/IP サーバーを設計するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。