1.ネットワークプログラミングの概要
ネットワークプログラミングとは、インターネット上の2つ(またはそれ以上)のデバイス(コンピューターなど)間のデータ転送を可能にするプログラムを記述することです
1.目的:通信するネットワークプロトコルを介して他のコンピューターと直接または間接的にデータを通信します。
2.ネットワークプログラミングで注意すべき2つの問題
①ネットワーク上で1つ以上のホストを正確に見つけた場合は、ホスト上の特定のアプリケーションを見つけます
②ホスト発見後、確実かつ効率的にデータを転送する方法
2.ネットワーク通信における2つの重要な要素
要素1、IPおよびポート番号:
①IP:インターネット上のコンピューターを一意に識別します(抽象化しすぎて覚えにくい)②ポート
番号:ホスト上の特定のアプリケーション(プロセス)を見つけます
③IP分類:IPv4とIPv6、World Wide Webとローカルエリアネットワークの
違い④JavaでInetAddressクラスはIPを表します
。⑤ドメイン名:www.baidu.com DNS(ドメイン名解決サーバー)。これは、IPへのアクセスに使用できます。⑥
ローカルループアドレス:127.0.0.1対応:localhost
ポート番号:
①プロセスごとにポート番号が異なる
②は16ビット整数0-65535として指定されています
③
ポート分類認識ポート:0〜1023が定義済みサービス通信で占有(例:HTTPでポート80が占有)
登録ポート:ユーザープロセスまたはアプリケーションに割り当てられた1024〜49151(例:Tomcatはポート8080を使用し、MySQLはポート3306を使用)
動的/プライベートポート:49152〜65535
④ポート番号とIPアドレスの組み合わせにより、ネットワークソケットが生成されます。
要素2.ネットワーク通信プロトコル:(TCP / IP参照モデル)
概念:
コンピュータネットワークで通信を実現するには、いくつかの制約が必要です。つまり、レート、伝送コード、コード構造、伝送制御ステップ、エラー制御などの標準を設定する通信プロトコルです。
通信プロトコルの階層化:物理リンク層、IP層、トランスポート層、アプリケーション層
トランスポート層プロトコルには2つの重要なプロトコルがあります。
①伝送制御プロトコル(TCP)
②ユーザーデータグラムプロトコル(UDP)
TCP / IPプロトコル:これは、伝送制御プロトコル(TCP)およびネットワーク相互接続プロトコル(IP)にちなんで名付けられたプロトコルのグループであり、さまざまな機能を持ち、互いに関連する複数のプロトコルを含みます。
TCPとUDPの違い
TCPプロトコル:(ライフケース:呼び出し)
1. TCPプロトコルを使用する前に、TCP接続を確立して送信データチャネルを形成する必要があります
。2.送信前に、ポイントツーポイント通信に「スリーウェイハンドシェイク」方式を使用します。これは信頼性があります。3. TCP
通信の2つのアプリケーションプロセス:クライアント、サーバー
4.接続中に大量のデータを送信できます
5.送信が完了した後、確立された接続を解放する必要があるため、非効率的です
3つのハンドシェイク:
最初のステップ:クライアントは、synをサーバーに送信してハンドシェイクを開始します。
ステップ2:サーバーは、syn + ackを受け取った後、クライアントに応答します。
3番目のステップ:クライアントがsyn + ackを受信した後、サーバーのsyn + ackを受信したことを示すackでサーバーに応答します。
ブラウザとリモートWebサーバーは、TCPスリーウェイハンドシェイクネゴシエーションを介してTCP / IP接続を確立します。ハンドシェイクには、同期メッセージ、同期応答メッセージ、および応答メッセージが含まれており、これら3つのメッセージは、ブラウザとサーバーの間で転送されます。ハンドシェイクは最初にクライアントによる通信の確立を試み、次にサーバーがクライアントの要求に応答して受け入れ、最後にクライアントが要求が受け入れられたというメッセージを送信します。
3ウェイハンドシェイクの理由:無効なメッセージがサーバーに送信されるのを防ぐため。
4回振ります
ハンドの最初の波:データ送信が終了した後、クライアントアプリケーションプロセスは接続解放セグメントを送信し、データの送信を停止しますそのヘッダー:FIN = 1、seq = x。
2番目の波:接続解放メッセージセグメントを受信した後、サーバーは確認メッセージを送信します。そのヘッダーは次のとおりです:ack = x + 1、seq = z。この時点で、接続はセミクローズ状態になり、クライアントはサーバーにデータを送信しなくなりました。サーバーは送信を続けます。
3番目の波:サーバーにクライアントに送信するデータがない場合、そのアプリケーションプロセスはサーバーにTCP接続を解放するよう通知します。
4番目の波:クライアントが接続解放セグメントを受信した後、2MSL(メッセージの最大寿命)の後で、このTCP接続は実際に終了し、通信パーティは別れを完了しました。
UDPプロトコル:(ライフケース:SMSを送信)
1.接続を確立せずに、データ、送信元、および宛先をデータパケットにカプセル化する
2.各データグラムのサイズは64kに制限されています
3.相手が使用可能かどうかに関係なく、受信者は受信を確認しないため、信頼できません。
4.放送できます
5.データ送信の最後にリソースを解放する必要がなく、オーバーヘッドが小さく、速度が速い
ネットワーク内のホスト間の通信を実現する方法
1.通信の両当事者のアドレス(IPおよびポート番号)
2.特定の規則(ネットワーク通信プロトコル)
InetAddressの2つのメソッドをインスタンス化する方法:getByName()、getLocalHost
2つの一般的な方法:
GETHOSTNAME()
はgetHostAddress()
public class InetAddressTest {
public static void main(String[] args) {
try {
//实例化
//getAllByName()
InetAddress inet = InetAddress.getByName("192.168.10.100");// --->/192.168.10.100
System.out.println(inet);
InetAddress inet1 = InetAddress.getByName("www.baidu.com");//www.baidu.com/39.156.66.14
System.out.println(inet1);
InetAddress inet2 = InetAddress.getByName("127.0.0.1");// /127.0.0.1
System.out.println(inet2);
//获取本机的IP地址
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);//
//getHostName()
//getHostAddress()
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
第三に、TCPネットワークプログラミングの実現
1.クライアントがサーバーに情報を送信し、サーバーがデータをコンソールに表示します。
注:最初にサーバーを起動し、次にクライアントを起動します
public class TCPTest {
/*
客户端
*/
@Test
public void client(){
Socket socket = null;
OutputStream ops = null;
try {
//1.实例化对象,指明ip和端口号
InetAddress inet = InetAddress.getByName("127.0.0.1");
socket = new Socket(inet,8899);
//2.获取输出字节流,用于输出数据
ops = socket.getOutputStream();
//3.写出数据
ops.write("你好,我是客户端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.资源关闭
if (ops!=null){
try {
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
服务端:接收客户端的数据
*/
@Test
public void server() {
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//指明端口号和
//1.实例化服务器端的ServerSocket对象,指明自己的端口号
ss = new ServerSocket(8899);
//2.调用accept(),接收来自客户端的socket
socket = ss.accept();
//3.获取输入流
is = socket.getInputStream();
//过程,不建议,可能会乱码
// byte[] bytes =new byte[1024];
// int len;
// while ((len = is.read(bytes)) != -1){
// String string =new String(bytes,0,len);
// System.out.println(string);
// }
//4.读取输入流中的数据
baos = new ByteArrayOutputStream();
byte[] bytes = new byte[5];
int len;
while ((len = is.read(bytes)) != -1){
baos.write(bytes,0,len);
}
System.out.println(baos.toString());
//收到来自谁的数据,获取客户端的Ip地址
System.out.println("收到了来自:"+socket.getInetAddress().getHostAddress()+"的信息");
} catch (IOException e) {
e.printStackTrace();
} finally {
//5.关闭资源
if (baos!=null){
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss!=null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
効果のデモ:
2.クライアントはファイルをサーバーに送信し、サーバーはファイルをローカルに保存します。
IOExceptionをスローする代わりに、try-catch-finallyを使用する必要があります
public class TCPTest1 {
/*
客户端
*/
@Test
public void client() throws IOException {
//1.创建socket对象,指定ip和端口号
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
//2.获取输出流
OutputStream os = socket.getOutputStream();
//3.获取输入流
FileInputStream fis = new FileInputStream(new File("IO流的分类.png"));
//4.具体的读写过程
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1){
os.write(bytes,0,len);
}
//5.关闭资源
fis.close();
os.close();
socket.close();
}
/*
服务端
*/
@Test
public void server() throws IOException {
//1.创建ServerSocket对象,指定自己的端口号
ServerSocket ss = new ServerSocket(9090);
//2.使用accept(),获取客户端的socket
Socket socket = ss.accept();
//3.获取客户端的输入流
InputStream is = socket.getInputStream();
//4.指明输出的位置
FileOutputStream fos = new FileOutputStream(new File("IO流的分类2.png"));
//5.具体的操作过程
byte[] bytes = new byte[1024];
int len;
while ((len = is.read(bytes)) != -1){
fos.write(bytes,0,len);
}
System.out.println("接收成功");
//6.资源关闭
fos.close();
is.close();
socket.close();
ss.close();
}
}
3.ファイルをクライアントからサーバーに送信します。サーバーはそれをローカルに保存し、「正常に送信されました」をクライアントに返します。
public class TCPTest2 {
/*
客户端
*/
@Test
public void client() throws IOException {
//1.创建socket对象,指定ip和端口号
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
//2.获取输出流
OutputStream os = socket.getOutputStream();
//3.获取输入流
FileInputStream fis = new FileInputStream(new File("IO流的分类.png"));
//4.具体的读写过程
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1){
os.write(bytes,0,len);
}
//关闭数据的输出,服务器就会得到明确的指示,如果没有shutdownOutput(),就会被read()阻塞,执行不了下面的操作
socket.shutdownOutput();
//5.接收来自于服务端的数据,并显示到控制台上
InputStream is = socket.getInputStream();
//为了不乱码,使用ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes1 = new byte[5];
int len1;
while ((len1 = is.read(bytes1)) != -1){
baos.write(bytes1,0,len1);
}
//显示数据
System.out.println(baos.toString());
//6.关闭资源
fis.close();
os.close();
socket.close();
baos.close();
}
/*
服务端
*/
@Test
public void server() throws IOException {
//1.创建ServerSocket对象,指定自己的端口号
ServerSocket ss = new ServerSocket(9090);
//2.使用accept(),获取客户端的socket
Socket socket = ss.accept();
//3.获取客户端的输入流
InputStream is = socket.getInputStream();
//4.指明输出的位置
FileOutputStream fos = new FileOutputStream(new File("IO流的分类4.png"));
//5.具体的操作过程
byte[] bytes = new byte[1024];
int len;
//read()为阻塞式方法,一直停留在循环中
while ((len = is.read(bytes)) != -1){
fos.write(bytes,0,len);
}
//6.服务端给客户端反馈
System.out.println("发送成功!");
OutputStream os = socket.getOutputStream();
os.write("数据发送成功".getBytes());
//7.资源关闭
fos.close();
is.close();
socket.close();
ss.close();
os.close();
}
}
4、UDPプロトコルネットワークプログラミング
/*
发送端
*/
@Test
public void sender() throws IOException {
//1.实例化DatagramSocket
DatagramSocket socket = new DatagramSocket();
//2.数据的声明
String str = "UDP的网络编程";
//3.转换为字节数组
byte[] data = str.getBytes();
//4.指定ip
InetAddress inet = InetAddress.getLocalHost();
//5.实例化DatagramPacket(数据报)
DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090);
//6.发送数据报
socket.send(packet);
//7.关闭资源
socket.close();
}
/*
接收端
*/
@Test
public void receiver() throws IOException {
//1.实例化DatagramSocket,指定自己的端口号,确定自己的进程
DatagramSocket socket = new DatagramSocket(9090);
//2.数据封装在DatagramPacket,不再发送,不用指定端口号和ip
byte[] bytes = new byte[100];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
//3.接收数据
socket.receive(packet);
//4.输出数据
//packet.getData()获取packet中的数据,从0开始,到哪里结束
System.out.println(new String(packet.getData(),0,packet.getLength()));
//5.资源关闭
socket.close();
}
5、URLネットワークプログラミング
1. URL(Uniform Resource Locator):インターネット上のリソースのアドレスを表すUniform Resource Locator
2. URLの基本構造は5つの部分で構成されています。
<転送プロトコル>:// <ホスト名>:<ポート番号> / <ファイル名>#クリップ名?パラメータリスト
例:http://192.168.1.100:8080/helloworld/index.jsp?ユーザー名=管理者&パスワード= 123456
3.共通メソッド:
public String getProtocol():URLのプロトコル名を取得します
public String getHost():URLのホスト名を取得します
public String getPort():URLのポート番号を取得します
public String getPath():URLのファイルパスを取得します
public String getFile():URLのファイル名を取得します
public String getQuery():URLのクエリ名を取得します
public class URLTest {
public static void main(String[] args) {
try {
URL url = new URL("http://192.168.1.100:8080/helloworld/index.jsp?username=admin&password=123456");
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
URLネットワークプログラミングを使用してTomcatにファイルをダウンロードする
public class URLTest1 {
public static void main(String[] args) {
HttpURLConnection urlConnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
//下载Tomcat服务器中的数据,需要开启Tomcat服务器
URL url =new URL("http://192.168.1.100:8080/helloworld/IO流的分类.png");
//找到连接对象
urlConnection = (HttpURLConnection) url.openConnection();
//获取连接,访问服务器
urlConnection.connect();
//得到一个输入流
is = urlConnection.getInputStream();
//将从服务器得到的数据,写入到具体的文件中,再main方法中,会写入到当前工程下
fos = new FileOutputStream("IO流的分类5.png");
//读写过程
byte[] bytes = new byte[1024];
int len;
//读取文件
while ((len = is.read(bytes)) != -1){
//写入到文件中
fos.write(bytes,0,len);
}
System.out.println("下载完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConnection != null){
//断开连接
urlConnection.disconnect();
}
}
}
}