ネットワークプロセス間で通信する方法
ローカルプロセス間通信(IPC)の間に多くの方法がありますが、次の4つのカテゴリーでまとめることができます。
-
メッセージング(パイプ、FIFO、メッセージキュー)
-
同期(ミューテックス、条件変数、読み書きロック、書き込みレコードファイルロック、セマフォ)
-
共有メモリ(匿名と命名)
-
リモートプロシージャコール(SolarisのドアとSun RPC)
しかし、これらは、この資料の対象ではありません!私たちは、ネットワークのプロセス間通信方法を議論したいですか?主な問題は、一意論外プロセスやコミュニケーションを特定する方法です!ローカルで一意にPIDによるプロセスを識別することができますが、ネットワークは、それが動作しません。実際には、TCP / IPプロトコルスイートは、私たちはこの問題、ネットワーク上の一意に識別するホストネットワーク層の「IPアドレス」、およびトランスポート層一意のホスト(プロセス)を識別することができ、「プロトコル+ポート」アプリケーションを解決するために役立っています。したがって、他のプロセスと対話するためにこのフラグを使用することができ、プロセス、プロセス通信ネットワークを識別することができるネットワークに三重(IPアドレス、プロトコル、ポート)を使用。
プロセス間のネットワーク通信に、UNIX BSDソケット(ソケット)TLIとUNIXシステムV(それが除去されている)のTCP / IPプロトコル・アプリケーション・プログラミング・インターフェースは、一般的に使用されるアプリケーションを使用して。今のところ、ほとんどすべてのアプリケーションがソケットに基づいていますが、今のインターネットの時代ですが、ネットワークのプロセス間通信は、「すべてはソケット」理由である、どこにでもあります。
TCPの概要
1.TCPはじめに
A> TCPプロトコル:TCPプロトコル、伝送制御プロトコル(英語:と略記伝送制御プロトコル:TCP)は、コネクション指向の、信頼性の高いバイトストリームプロトコルベースの通信であります
1.コネクション型:コールモデルのような第一のコネクタ、及びその後の通信は、
2.信頼性の高い、UDPに対して、TCPは伝送の信頼性を保証するために、より信頼性の高い伝達機構(コネクション型機構、送信応答機構)によってTCPシーケンスであります
3.バイトストリームに基づいて、UDPは、UDPソケットを作成 - DGRAM:データグラムベースの通信システムを、各送信されたデータは、ターゲット・ホスト、ポート番号のIPアドレスを含む、独立したエンティティであり、コンテンツデータが送信されます
B> 3つの段階TCP通信
ベースの接続指向:サーバーとの接続を確立するために、1。
2.送受信データ
3.接続を閉じます
2.TCPの特長
A>コネクション指向
1.最初の接続を確立し、その後、通信
2.TCP接続は1対1または1対多でもよくUDP、UDP適切な放送用番組
A>信頼性の高い伝送:TCPはUDPの送信よりも信頼性が高いデータを保護するためのメカニズムのシーケンスにより、
1.送信応答機構
2.タイムアウト再送メカニズム
3.エラーチェック
4.フロー制御/輻輳管理
JavaSocketプログラミング
Java環境では、ソケットは、プログラミング主にTCP / IPプロトコルに基づいてネットワークプログラミングを指します。
ソケットのワークプロセスは、以下の4つのステップで構成されています。
(1)ソケットを作成します。
(2)入力/出力ストリームへのオープンソケット接続。
(3)ソケット、リード/ライト動作のための特定のプロトコルに従いました。
(4)閉じるソケット
JavaのSocketクラスは、2が含まれています:ソケット(クライアント)とのServerSocket(サーバー)
1)Socketクラス
ソケットクラス:このクラスを実装クライアントソケット、ソケットは、2つのデバイス間の通信のエンドポイントを指します。コンストラクタ公共のソケット(文字列のホスト、int型ポート ): 指定されたホスト上のソケット接続オブジェクトと指定したポート番号を作成します。指定されたホストがnull、ループバックアドレスに指定したアドレスに相当します。
メンバーの方法:
公共のInputStreamのgetInputStream():このソケットの入力ストリームを返します。このScoketに関連するチャネルを有する場合、生成された操作入力ストリームの全ては、チャネルに関連付けられています。クローズ生成されたInputStreamが関連付けられているソケットを閉じます。
公共のOutputStreamのgetOutputStream():このソケットの出力ストリームを返します。このScoketに関連するチャネルを有する場合、生成された操作のOutputStreamの全ては、このチャネルに関連付けられています。クローズ生成されたOutputStreamは、関連付けられたソケットを閉じます。
公共のボイド近い():このソケットを閉じます。ソケットが閉じられると、それは再利用することはできません。閉じるこのソケットは、関連付けられたInputStreamとOutputStreamを閉じます。
ます。public void shutdownOutput():無効ソケット出力ストリーム。以前に書き込まれたデータが出力ストリームを終了する、送信します。
2)クラスのServerSocket
のServerSocketクラス:このクラスを実装し、サーバソケット、オブジェクトは、ネットワーク上の要求を待っています。
コンストラクタ
公共のServerSocket(INTポート):ServerSocketオブジェクトを作成するときにこの構成方法では、特定のポート番号にバインドすることができ、ポート番号は、ポートパラメータです。
設定例は、次のように:ServerSocketのサーバーは=新しいServerSocketを(6666);
メンバー方法
公共ソケット)が(受け入れ:リッスンし、接続を受け入れ、新しいSocketオブジェクトを返し、クライアントが通信するため。このメソッドは、
接続が確立されるまでブロックします。
詳細な接続を確立するために、TCP 3ウェイハンドシェイクでソケット
私たちは、「3ウェイハンドシェイク」そのやり取り3つのパケットへの接続を確立するTCP知っています。プロセスは、実質的に、以下:
- クライアントはサーバSYN Jを送信します
- クライアントにSYN K、およびSYN J確認ACK J + 1とサーバの応答
- クライアントサーバの考えは、確認応答ACK K + 1を送信します
唯一の3ウェイハンドシェイクが完了しますが、この3ウェイハンドシェイクでそのいくつかの機能は、その中のソケットに発生するでしょうか?以下を参照してください。
从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。
socket中TCP的四次握手释放连接详解
上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:
图示过程如下:
-
某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
-
另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
-
一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
-
接收到这个FIN的源发送端TCP对它进行确认。
这样每个方向上都有一个FIN和ACK。
Java的Socket库函数与Linux的Socket系统调用之间的区别:
Java通过JVM实现了优良的跨平台性,同一段写好的代码,移植到不同的操作系统上可直接执行,不受操作系统的限制,一处编译,到处执行,JAVA的SOCKET编程的底层原理是JVM将JAVA程序解析出来的参数传递给所对应的C++程序,由C++执行完之后回传给JAVA。
而LINUX自带的SOCKET编程只能再LINUX操作系统下使用,同时JAVA与LINUX的API也不一致。
一个小例子:
服务端代码:
package ray; import java.io.*; import java.net.*; public class Server { private static ServerSocket server; public static void main(String[] args) throws IOException{ server = new ServerSocket(1100); System.out.println("服务器启动成功,等待用户接入..."); //等待用户接入,直到有用户接入为止,Socket对象表示客户端 Socket client = server.accept(); //得到接入客户端的IP地址 System.out.println("有客户端接入,客户IP:" + client.getInetAddress()); InputStream in = client.getInputStream();//从客户端生成网络输入流,用于接收来自网络的数据 OutputStream out = client.getOutputStream();//从客户端生成网络输出流,用来把数据发送到网络上 byte[] bt = new byte[1024];//定义一个字节数组,用来存储网络数据 int len = in.read(bt);//将网络数据写入字节数组 String data = new String(bt, 0 , len);//将网络数据转换为字符串数据 System.out.println("来自客户端的消息:" + data); out.write("我是服务器,欢迎光临".getBytes());//服务器端数据发送(以字节数组形式) client.close();//关闭套接字 } }
客户端代码:
package ray; import java.io.*; import java.net.*; public class Client { private static Socket client; public static void main(String[] args) throws UnknownHostException, IOException { client = new Socket("127.0.0.1", 1100); System.out.println("连接服务器成功"); InputStream in = client.getInputStream();//从客户端生成网络输入流,用于接收网络数据 OutputStream out = client.getOutputStream();//从客户端生成网络输出流,用来发送数据 out.write("我是客户端,欢迎光临".getBytes());//客户端数据发送 byte[] bt = new byte[1024];//定义一个字节数组,用来存储网络数据 int len = in.read(bt);//将网络数据写入字节数组 String data = new String(bt, 0 ,len);//将网络数据转换为字符串数据 System.out.println("来自服务器的消息:" + data); client.close();//关闭套接字 } }
运行结果展示:
服务器端: