NET Socket開発の同期Socketを2つ実現しました.

5142 ワード

今日は私たちに話してみます.NETネットワークアプリケーションの開発では、同期ソケットのアプリケーションを同期させるために、多くの人が、ネットワークアプリケーションのサービス端末であるソケットは同期ソケットを使うべきではないと考えています.下の二つのシーンのように、同期のソケットを使うことが考えられます.
一、クライアントの数が少ない:
数が少ないということは、サーバーに同時に接続するクライアントの数が一般的に50人以下ということです.このような状況では、同期Socketc+Threadを使ってサービスを実現することが考えられます.このようにして、より明確なコードを作成します.性能はあまり落ちません.
二、クライアントの数が多いですが、短い接続です.
ショートコネクションとは、クライアントの接続が一回の送受信後に生産され、すぐに切断されるシーンのことで、例えばHTTPプロトコルは短い接続です.HTTPは、クライアントからの要求時にソケット接続を確立し、ソケットを介してURL要求を発行し、この要求を処理して該当ページに返信すると、この接続を切断します.このような場面では、同期ソケットを使って私たちのニーズを実現することもできます.
もし上記の二つの要求を実現すればいいですね.この二つの需要に対して、私は異なる方案を採用してそれらを実現します.
まず第一の需要を見てみます.ここではソケット+Threadを採用して実現します.基本的な流れは以下の通りです.
まず、Socketを作成し、EndPointをバインドしてから傍受を開始します.次にスレッドを作成し、このスレッドでクライアントからの接続要求を無限ループで受信する.要求を受信した後、このクライアントのために新しいスレッドを作成し、このスレッドでも無限ループを使用してこのクライアントからのデータを受信します.コードを見てみましょう.
まず、クライアントの接続をヒアリングするためのソケットを作成します.
 
Socket listener = new Socket(AddressFamily.InterNetwork, 
SocketType.Stream, ProtocolType.Tcp); IPEndPoint locEP= new IPEndPoint(IPAddress.Any, 2000); listener.Bind(locEP); listener.Listen(100);
 
次に、クライアントの接続要求を処理するスレッドを作成する.
 
Thread acceptThread = new Thread(new ThreadStart(AcceptWorkThread));
acceptThread.Start();
 
private void AcceptWorkThread()
...{
    Thread.CurrentThread.IsBackground = true;
    while (true)
    ...{
        Socket accept = listener.Accept();
        IPEndPoint remoEP = (IPEndPoint)accept.RemoteEndPoint;
        string recString = "     " + remoEP.Address.ToString() + "   。";
        this.Invoke(new AddListItemHandler(this.AddListItem), new string[] ...
{ recString }); Thread receiveThread = new Thread(new ParameterizedThreadStart
(ReceiveWorkThread)); receiveThread.Start(accept); } }
 
最後に、データの受信方法を見てみましょう.
 
private void ReceiveWorkThread(object obj)
...{
    Thread.CurrentThread.IsBackground = true;
    Socket socket = (Socket)obj;
    byte[] buffer = new byte[1024];
    while (true)
    ...{
        int receiveCount = socket.Receive(buffer);
        if (receiveCount > 0)
        ...{
            IPEndPoint remoEP = (IPEndPoint)socket.RemoteEndPoint;
            string recString = "     " + remoEP.Address.ToString() + " 
:" + Encoding.Default.GetString(buffer, 0, receiveCount); this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); socket.Send(buffer, receiveCount, SocketFlags.None); } else ...{ socket.Close(); break; } } }
 
はい、実現したら完成します.
今は第二の需要を見てみましょう.
この方案はもう一つの方法で実現します.なぜ前の方法を採用しないで実現しますか?分析してみましょう.前の実装では、クライアントにアクセスするごとにスレッドが作成され、クライアントが大量にアクセスすると、スレッドが作成されることを知っています.しかし、スレッドが多すぎると、Windowsはより多くのCPU時間を必要としてスレッドのコンテキストを切り替える(これも前の実装では多くのクライアントにアクセスできない理由である).
私たちはこのスキームでは、各接続が短い接続であることを知っています.そして順番は決まっています.すべては、アクセス->受信->送信のような順序であり、1つの方法で全体の処理を完了することができる.このようにして、私達はスレッド池を利用して私達の必要なものを実現することができます.じゃ、コードで話しましょう.
まず、クライアントの接続をヒアリングするためのソケットを作成します.
 
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp); IPEndPoint locEP= new IPEndPoint(IPAddress.Any, 2000); listener.Bind(locEP); listener.Listen(100);
 
次にスレッドを作成します.
 
Thread[] ClientThreadList = new Thread[30];
foreach (Thread th in ClientThreadList)
...{
    th = new Thread(new ThreadStart(ClientWorkThread));
    th.Start();
}
 
最後にスレッドを見てみましょう.何をしますか?
 
private void ClientWorkThread()
...{
    byte[] buffer = new byte[1024];
    while (true)
    ...{
        Socket socket = listener.Accept();
        string recString = "     " + remoEP.Address.ToString() + "   。
"; this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); int receCount = socket.Receive(buffer); if (receCount>0) ...{ string recString = " " + remoEP.Address.ToString() + "
:" + Encoding.Default.GetString(buffer, 0, receiveCount); this.Invoke(new AddListItemHandler(this.AddListItem), new string[]
...{ recString }); socket.Send(buffer, receCount, SocketFlags.None); } socket.Shutdown(SocketShutdown.Both); socket.Close(); } }
 
なぜ私たちはこうしますか?
まず、クライアントの接続要求をヒアリングするためのソケットを作成しました.次に、30スレッドを持つスレッドプールを作成しました.そして、各スレッドでAcceept、Receive、Send、Close()を実現し、接続、受信、送信、クローズの動作を完了する.
ここで、クライアントがサーバに接続したと仮定します.この要求に対してスレッドAcceptがあり、クライアントから送信されたデータを受信し、データを受信したら処理してクライアントに送信し、この接続をオフにして、再度接続待ち状態に入ります.他の29スレッドはAcceptからこの要求がないため、まだアクセス待ち状態を処理している.
 
本論文の転送先:http://www.beidaqingniao.org/edu/e/web/797.html