C#に基づくTCP / IPプロトコルの適用(1)

1.背景とコンセプト

1.標準イーサネット

イーサネットは、1975年にゼロックスコーポレーションのパロアルトリサーチセンターによって開発に成功し、そのコアテクノロジーはALOHAネットワークに端を発しています。現在、イーサネットとは、IEEE 802.3標準に準拠するローカルエリアネットワーク(LAN)製品グループを指します。IEEE802.3は、有線の物理層とデータリンク層を定義するIEEE(Institute of Electrical and Electronics Engineers)標準のセットです。イーサネットメディアアクセス制御。イーサネットネットワークを構成するためのルールと、さまざまなネットワーク要素が互いにどのように連携するかについて説明します。イーサネットは次のように分類されます
。1。標準イーサネット:初期の10Mbpsイーサネットは標準イーサネットと呼ばれ、同軸ケーブルとネットワークカード(ネットワークアダプタ)で構成されるバスタイプのローカルエリアネットワークです。
ここに画像の説明を挿入
データの送受信は、CSMA / CDプロトコルを介して完了します。このプロセスは、最初にリッスンして送信、送信中にリッスン、競合停止、再送信の遅延の4つのポイントに簡単に要約できます
2.バスイーサネットは、リピーターとブリッジを介して拡張されます。
リピーター(リピーター)は、リピーターとも呼ばれ、伝送媒体内の減衰信号を増幅して、ケーブルの伝送距離を伸ばします。
ブリッジとも呼ばれるブリッジは、ストアアンドフォワードデバイスです。データリンク層で動作し、フレームを受信すると、最初にフレームの宛先MACアドレスをチェックし、次にフレームが転送されるポートを決定します。
イーサネットには、ハブベースのイーサネット、スイッチベースのイーサネットなど、さまざまな種類があり、現在では10万ギガビットイーサネットに発展しています。

2.産業用イーサネット

産業用イーサネットとは、一般に、商用イーサネット(IEEE802.3標準)と技術的に互換性があることを意味しますが、製品設計では、材料の選択、製品の強度、適用性、およびリアルタイムのパフォーマンスに関する産業用サイトの要件を満たすことができます。必要。
現在、HSE、Modbus TCP / IP、ProfINet、Ethernet / IPの4つの主要プロトコルが含まれています。
Foundation Fieldbus FFは、2000年にHSE(高速イーサネット)と呼ばれるイーサネット仕様をリリースしました。
Modbus TCP / IPプロトコルはSchneiderによって立ち上げられました。これは、Modbusフレームを非常に簡単な方法でTCPフレームに埋め込み、ModbusをイーサネットおよびTCP / IPと組み合わせます。
ドイツのシーメンスは2001年に、オリジナルのProfibusとインターネットテクノロジーを組み合わせたProfiNetネットワークソリューションをリリースしました。ProfiNetは、標準のTCP / IPプロトコルとアプリケーション層RPC / DCOMを使用して、ノード間の通信とネットワークアドレス指定を完了します。
Ethernet / IPは、CIP(Control and Information Proto-Col)プロトコルに基づいた、産業環境アプリケーションに適したプロトコルシステムです。これは、ネットワーク上で暗黙的(制御)リアルタイムI / O情報と明示的情報(構成、パラメーター設定、診断などを含む)を効果的に送信できるようにするオブジェクト指向プロトコルです。
産業用イーサネット機器には、次の重要な部品が含まれ
ます。1。産業用イーサネットハブ
2.産業用イーサネットアンマネージドスイッチ
3.産業用イーサネットマネージドスイッチ
4.産業用イーサネットマネージド冗長スイッチ

3. TCP / IPプロトコル

ここに画像の説明を挿入
上記の表は、ネットワークプロトコルの基本的な機能とプロトコルを示しています。TCP(伝送制御プロトコル)プロトコルはトランスポート層にあり、IP(インターネットプロトコル)プロトコルはネットワーク層にあります。
1. TCPプロトコル:コネクション型で信頼性の高いバイトストリームベースのトランスポート層通信プロトコルです。信頼性の低いインターネットネットワークで信頼性の高いエンドツーエンドのバイトストリームを提供するために特別に設計された伝送プロトコルです。インターネットワークは、単一のネットワークとは大きく異なります。これは、インターネットワークのさまざまな部分で、トポロジ、帯域幅、遅延、パケットサイズ、およびその他のパラメータが大きく異なる場合があるためです。TCPの設計目標は、インターネットのこれらの特性に動的に適応し、さまざまな障害に直面しても堅牢になることです。
ここに画像の説明を挿入
IPプロトコル
2. IPプロトコル:ネットワーク間の情報転送用のプロトコルであり、送信元デバイス(ユーザーのコンピューターなど)から宛先デバイス(特定の部門のwwwサーバーなど)にIP情報パケットを転送できます。その目的は、インターネットの問題を解決し、大規模で異種のネットワークの相互接続と相互運用性を実現することです。2つ目は、トップレベルのネットワークアプリケーションとボトムレベルのネットワークテクノロジー間の結合関係を分割して、2つの独立した開発を促進することです。
3.スリーウェイハンドシェイク、4回ブレークアップ
ここに画像の説明を挿入
、SYN:シーケンス番号の同期。これは、TCP / IPが接続を確立するときに使用されるハンドシェイク信号です。ACK:ACK(確認文字)は確認文字です。データ通信において、受信局から送信局に送信される送信制御文字。送信されたデータが正しく受信されていることが確認されたことを示します。
FIN_WAIT:FIN_WAIT_1とFIN_WAIT_2はどちらも、互いのFINメッセージを待機していることを示します。
4.ソケット
アプリケーション層とトランスポート層はソケットで区切られています。ソケットには、リモートに接続されているローカルポート情報(ローカルアドレスとポート番号)と、リモートに接続されているリモートポート情報(リモートアドレスとポート番号)の2つの情報が含まれています。
5. TcpClientとTcpListener。NET
は、ソケットのプログラミングをカプセル化するためにこれら2つのクラスを提供します。
ここに画像の説明を挿入
通常、接続を開始する側はクライアントと呼ばれ、もう一方はサーバーと呼ばれます。これで、サーバーは初期接続を確立する必要があるため、常にTcpListenerクラスを使用していると結論付けることができます。

IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
            TcpListener listener = new TcpListener(ip, 8500);

            listener.Start();           // 开始侦听
            Console.WriteLine("Start Listening ...");

ポート8500:サービスリスト、登録サービス、キャンセルサービスを取得するためのHTTPインターフェイスを提供します。cmd:netstat-aを使用してUIサービスを提供します。
新しいTcpClientが作成されるたびに、と通信するための新しいソケットソケットを作成するのと同じです。サーバー通信のために、.Netはこのソケットにポート番号を自動的に割り当て
ます。TcpClientタイプのインスタンスを作成するときに、コンストラクターでリモートサーバーのアドレスとポート番号を指定できます。このようにして、作成と同時に接続要求(「ハンドシェイク」)がリモートサーバーに送信され、成功すると、2つの間の接続が確立されます。オーバーロードされたパラメーターなしのコンストラクターを使用してオブジェクトを作成してから、Connect()メソッドを呼び出し、Connect()メソッドでリモートサーバーのアドレスとポート番号を渡して、サーバーとの接続を確立することもできます。パラメータ化されたコンストラクタを使用するサーバーへの接続、またはConnect()メソッドを介したサーバーとの接続の確立は、同期メソッド(またはブロッキング、英語ではブロックと呼ばれます)です。
6.ポート通信
サーバーとの接続が確立されると、この接続を介してデータを送受信できます。データは、ストリームの形式でポートとポート間で転送されます。ほとんどすべてのオブジェクトをストリームに保存できるため、クライアントとサーバー間で任意のタイプのデータを転送できます。クライアントにとって、ストリームへのデータの書き込みはサーバーへのデータの送信を意味し、ストリームからのデータの読み取りはサーバーからのデータの受信を意味します。サーバーの場合、ストリームへのデータの書き込みはクライアントへのデータの送信を意味し、ストリームからのデータの読み取りはクライアントからのデータの受信を意味します。

2、例

1.クライアントとサーバー間の接続を確立します

それぞれ2つのコンソールプログラムを作成します。

class Client
    {
        static void Main(string[] args)
        {
            TcpClient client = new TcpClient();
            try
            {
                client.Connect("local", 8500);  
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            Console.WriteLine("Server Connected!{0} --> {1}",client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
        }
    }
static void Main(string[] args)
        {
            Console.WriteLine("Server is running ... ");
            IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
            TcpListener listener = new TcpListener(ip, 8500);
            listener.Start();       
            Console.WriteLine("Start Listening ...");

            TcpClient remoteClient = listener.AcceptTcpClient();
            Console.WriteLine("Client Connected!{0} <-- {1}",remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);                
        }

結果は表示されず、とにかく成功し、2つのアプリケーションが接続を確立しました。

2.クライアントが複数のリクエストを行う

static void Main(string[] args)
        {
            const int BufferSize = 8192;    
            Console.WriteLine("Server is running ... ");
            IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
            TcpListener listener = new TcpListener(ip, 8500);
            listener.Start(); 
            Console.WriteLine("Start Listening ...");

            TcpClient remoteClient = listener.AcceptTcpClient();
            Console.WriteLine("Client Connected!{0} <-- {1}",remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
            NetworkStream streamToClient = remoteClient.GetStream();
            do
            {
                byte[] buffer = new byte[BufferSize];
                int bytesRead = streamToClient.Read(buffer, 0, BufferSize);
                Console.WriteLine("Reading data, {0} bytes ...", bytesRead);

                string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Received: {0}", msg);
            } while (true);
        }
class Client
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Client Running ...");
            TcpClient client;
            try
            {
                client = new TcpClient();
                client.Connect("localhost", 8500);      
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            Console.WriteLine("Server Connected!{0} --> {1}",
                client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
           
            NetworkStream streamToServer = client.GetStream();
            ConsoleKey key;
            Console.WriteLine("Menu: M - Send, G - Exit");
            do
            {
                key = Console.ReadKey(true).Key;

                if (key == ConsoleKey.M)
                {
                    Console.Write("Input the message: ");
                    string msg = Console.ReadLine();

                    byte[] buffer = Encoding.Unicode.GetBytes(msg);    
                    streamToServer.Write(buffer, 0, buffer.Length);  
                    Console.WriteLine("Sent: {0}", msg);
                }
            } while (key != ConsoleKey.G);
            //client.Close();
        }
    }

### 3.サーバーは処理された文字を送り返します。サーバー
はクライアントから送信された文字列を傍受し、クライアントに送り返します。

static void Main(string[] args)
        {
            const int BufferSize = 8192;   
            ConsoleKey key;

            Console.WriteLine("Server is running ... ");
            IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
            TcpListener listener = new TcpListener(ip, 8500);
            listener.Start();           
            Console.WriteLine("Start Listening ...");

            TcpClient remoteClient = listener.AcceptTcpClient();
            Console.WriteLine("Client Connected!{0} <-- {1}",
                remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);

            NetworkStream streamToClient = remoteClient.GetStream();
            do
            {
                byte[] buffer = new byte[BufferSize];
                int bytesRead;
                try
                {
                    lock (streamToClient)
                    {
                        bytesRead = streamToClient.Read(buffer, 0, BufferSize);
                    }
                    if (bytesRead == 0) throw new Exception("读取到0字节");
                    Console.WriteLine("Reading data, {0} bytes ...", bytesRead);
                    string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
                    Console.WriteLine("Received: {0}", msg);
                    msg = msg.Substring(2);
                    buffer = Encoding.Unicode.GetBytes(msg);
                    lock (streamToClient)
                    {
                        streamToClient.Write(buffer, 0, buffer.Length);
                    }
                    Console.WriteLine("Sent: {0}", msg);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            } while (true);

            streamToClient.Dispose();
            remoteClient.Close();

            Console.WriteLine("\n\n输入\"Q\"键退出。");
            do
            {
                key = Console.ReadKey(true).Key;
            } while (key != ConsoleKey.Q);
        }
class Client
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Client Running ...");
            TcpClient client;
            ConsoleKey key;
            const int BufferSize = 8192;
            try
            {
                client = new TcpClient();
                client.Connect("localhost", 8500);   
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }
            Console.WriteLine("Server Connected!{0} --> {1}",
                client.Client.LocalEndPoint, client.Client.RemoteEndPoint);           
            NetworkStream streamToServer = client.GetStream();
            Console.WriteLine("Menu: S - Send, X - Exit");
            do
            {
                key = Console.ReadKey(true).Key;

                if (key == ConsoleKey.S)
                {
                    Console.Write("Input the message: ");
                    string msg = Console.ReadLine();
                    byte[] buffer = Encoding.Unicode.GetBytes(msg);   
                    try
                    {
                        lock (streamToServer)
                        {
                            streamToServer.Write(buffer, 0, buffer.Length);
                        }
                        Console.WriteLine("Sent: {0}", msg);
                        int bytesRead;
                        buffer = new byte[BufferSize];
                        lock (streamToServer)
                        {
                            bytesRead = streamToServer.Read(buffer, 0, BufferSize);
                        }
                        msg = Encoding.Unicode.GetString(buffer, 0, bytesRead);
                        Console.WriteLine("Received: {0}", msg);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        break;
                    }
                }
            } while (key != ConsoleKey.X);
            streamToServer.Dispose();
            client.Close();
            Console.WriteLine("\n\n输入\"Q\"键退出。");
            do
            {
                key = Console.ReadKey(true).Key;
            } while (key != ConsoleKey.Q);        
        }
    }

3、TCPポートステータスの説明

1.リスニングステータス

FTP(File Transfer Protocol)サーバーは、クライアントとの接続が成功するまで、起動時にこの状態のままになります。

2.ESTABLISHEDステータス

接続が成功すると、この状態になります。これは、両端が通信していることを意味します。

3.CLOSE_WAIT状態

相手が積極的に接続を閉じるか、異常なネットワークにより接続が中断され、この状態になります。

4.TIME_WAIT状態

積極的にclose()を呼び出して切断すると、相手からの確認を受けてステータスがTIME_WAITになります。TCPプロトコルは、古い接続状態が新しい接続に影響を与えないようにするために、TIME_WAIT状態が2MSL(セグメントの最大存続期間の2倍)継続することを規定しています。

5.SYN_SENTステータス

SYN_SENT状態は、接続が要求されていることを意味します。他のコンピューターのサービスにアクセスする場合は、最初に同期信号をポートに送信する必要があります。このとき、状態はSYN_SENTです。接続が成功すると、ESTABLISHEDになります。 。現時点では、SYN_SENT状態は非常に短いです。SYN_SENTが多すぎて別のマシンに送信されている場合は、マシンが感染している可能性があります。

4、まとめ

ソケットの要約:
1。サーバーとクライアント間の接続を確立します。
2.クライアントはサーバーにメッセージを送信します。
3.サーバーはクライアントから接続を受信します。
4.サーバーはメッセージを処理し、クライアントに送信します。
5.クライアントがメッセージを受信します。
6.終了します。

参考記事:
イーサネット
7層ネットワークプロトコル-tcp / ipプロトコル
ネットワークプログラミング

おすすめ

転載: blog.csdn.net/baidu_35536188/article/details/114291257