1. InetAddressクラスの使用
1.1. ネットワーク通信を実現するには2つの問題を解決する必要がある
- ネットワーク上の 1 つ以上のホストを正確に特定する方法、ホスト上の特定のアプリケーションを特定する方法
- ホストを見つけた後にデータを確実かつ効率的に転送する方法
1.2. ネットワーク通信の 2 つの要素
- 対応する質問 1: IP とポート番号
- 対応する質問 2: ネットワーク通信プロトコルの提供: TCP/IP 参照モデル (アプリケーション層、トランスポート層、ネットワーク層、物理 + データリンク層)
1.3. 通信要素 1: IP とポート番号
- 知財の理解
- IP:インターネット上のコンピュータ(通信主体)を一意に識別するもの
- InetAddress クラスを使用して Java で IP を表現する
- IP 分類: IPv4 および IPv6、World Wide Web およびローカル エリア ネットワーク
- 域名:www.baidu.com、www.mi.com
- ドメイン名解決: ドメイン名は覚えやすいです。ネットワークに接続するときにホストのドメイン名を入力すると、ドメイン ネーム サーバー (DNS) がドメイン名を IP アドレスに変換する役割を果たします。ホストとの間で確立されます。
- ローカル ループ アドレス: 127.0.0.1 に対応: localhost
- InetAddress クラス: このクラスのオブジェクトは特定の IP アドレスを表します
- インスタンス化:
- getByName(文字列ホスト)
- getローカルホスト()
- 一般的な方法:
- ポート番号: コンピュータ上で実行されているプロセス
- 要件: プロセスごとに異なるポート番号
- 範囲: 16 ビット整数 0 ~ 65535 として指定します。
- ポート番号と IP アドレスの組み合わせにより、ネットワーク ソケットが生成されます: Socket
1.4. 通信要素 2: ネットワーク通信プロトコル
OSI参照モデル |
TCP/IP 参照モデル |
TCP/IP参照モデルの各層に対応するプロトコル |
アプリケーション層、プレゼンテーション層、セッション層 |
アプリケーション層 |
HTTP、FTP、Telnet、DNS… |
トランスポート層 |
トランスポート層 |
TCP、UDP... |
ネットワーク層 |
ネットワーク層 |
IP、ICMP、ARP… |
データリンク層、物理層 |
物理層 + データリンク層 |
リンク |
1.5、TCPとUDPの違い
- TCPプロトコル:
- TCP プロトコルを使用する前に、TCP 接続を確立して送信データ チャネルを形成する必要があります。
- 送信前は信頼性の高いポイントツーポイント通信「3ウェイハンドシェイク」方式
- TCP プロトコル通信のための 2 つのアプリケーション プロセス: クライアントとサーバー
- 接続内で大量のデータを転送できる
- 送信が完了したら、確立された接続を解放する必要があり、非効率的です
- UDPプロトコル:
- 接続を確立せずに、データ、送信元、宛先をパケットにカプセル化します。
- 各データグラムのサイズは 64K に制限されています
- 送信者の準備ができているかどうかに関係なく、受信者は受信を確認しないため、信頼性がありません
- 放送できる
- データ送信終了時にリソースを解放する必要がなく、オーバーヘッドが低く高速です。
1.6、TCP 3 ウェイ ハンドシェイクおよび 4 ウェイ ウェーブ
2. TCPネットワークプログラミング
/**
* 客户端发送信息给服务端,服务端将数据显示在控制台上
*/
public class TCPTest1 {
// 客户端
@Test
public void client() {
Socket socket = null;
OutputStream os = null;
try {
// 1、创建Socket对象,指明服务器端的IP和端口号
InetAddress inet = InetAddress.getByName("127.0.0.1");
socket = new Socket(inet, 8899);
// 2、获取一个输出流,用于输出数据
os = socket.getOutputStream();
// 3、写出数据的操作
os.write("你好,我是客户端mm".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4、资源的关闭
if (os != null) {
try {
os.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();
// 4、读取输入流中的数据
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[5];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(socket.getInetAddress().getHostAddress() + ":" + baos.toString());
} 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();
}
}
}
}
}
/**
* 客户端发送文件给服务端,服务端将文件保存在本地
*/
public class TCPTest2 {
// 客户端
@Test
public void client () {
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
os = socket.getOutputStream();
fis = new FileInputStream(new File("beauty.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.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;
FileOutputStream fos = null;
try {
ss = new ServerSocket(9090);
socket = ss.accept();
is = socket.getInputStream();
fos = new FileOutputStream(new File("beauty1.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.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();
}
}
}
}
}
/**
* 从客户端发送文件给服务器,服务端保存到本地。并返回“发送成功”给客户端
* 并关闭相关的连接
*/
public class TCPTest3 {
// 客户端
@Test
public void client ()
{
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
os = socket.getOutputStream();
fis = new FileInputStream(new File("beauty.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 关闭数据的输出
socket.shutdownOutput();
// 接收来自于服务器端的数据,并显示到控制台上
is = socket.getInputStream();
baos = new ByteArrayOutputStream();
byte[] buffer1 = new byte[20];
int len1;
while ((len1 = is.read(buffer1)) != -1) {
baos.write(buffer1, 0, len1);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.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;
FileOutputStream fos = null;
OutputStream os = null;
try {
ss = new ServerSocket(9090);
socket = ss.accept();
is = socket.getInputStream();
fos = new FileOutputStream(new File("beauty2.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("图片传输完成");
// 服务器端给予客户单反馈
os = socket.getOutputStream();
os.write("你好,美女,照片我已收到,非常漂亮!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.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();
}
}
}
}
}
3. UDPネットワークプログラミング
public class UDPTest {
// 发送端
@Test
public void sender () {
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
String str = "我是UDP方式发送的导弹";
byte[] data = str.getBytes();
InetAddress inet = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(data, 0, data.length, inet, 9090);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
socket.close();
}
}
}
// 接收端
@Test
public void receiver () {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9090);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(), 0, packet.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
socket.close();
}
}
}
4. URLプログラミング
4.1. URL (Uniform Resource Locator) の理解
- インターネット上のリソース アドレスに対応するユニフォーム リソース ロケーター
4.2. URL の 5 つの基本構造
- プロトコル
- CPU名
- ポート番号
- リソースアドレス
- パラメータリスト
4.3、インスタンス化の方法
URL url = new URL("http://localhost:8080/examples/beauty.jpg?username=Tom")
4.4 一般的な方法
- public String getProtocol(): URLのプロトコル名を取得します。
- public String getHost(): URLのホスト名を取得します。
- public String getPort(): URLのポート番号を取得します。
- public String getPath(): URLのファイルパスを取得します。
- public String getFile(): URLのファイル名を取得
- public String getQuery(): URLのクエリ名を取得します。
4.5、対応する URL リソースを読み取り、ダウンロードできます
public static void main(String[] args) {
HttpURLConnection urlConnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("http://localhost:8080/examples/beauty.jpg");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
is = urlConnection.getInputStream();
fos = new FileOutputStream("day10\\beauty3.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}