网络编程

计算机网络:

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络通信的要素

通信双方地址:

  • ip
  • 端口号

规则:网络通信协议

TCP/IP参考模型,UDP,TCP

IP

  • ip地址:InetAddress
  • 唯一定位一台网络上计算机
  • 127.0.0.1:本机 localhost
  • ip地址的分类
    • ipv4 / ipv6
      • IPV4:127.0.0.1,4个字节组成,0~255,42亿
      • IPV6:2001:0ab3:cccc:4532:0000:1bbb:3344:acac,128位,8个无符号整数
    • 公网(互联网)- 私网(局域网)
  • 域名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.lesson01;

import java.net.InetAddress;
import java.net.UnknownHostException;

// 测试IP
public class TestInetAddress {
   public static void main(String[] args) {
       try {
           //查询本机地址
           InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
           System.out.println(inetAddress1);
           InetAddress inetAddress2 = InetAddress.getByName("localhost");
           System.out.println(inetAddress2);
           InetAddress inetAddress3 = InetAddress.getLocalHost();
           System.out.println(inetAddress2);

           // 查询网站ip地址
           InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
           System.out.println(inetAddress4);

           // 常用方法
           System.out.println(inetAddress4.getAddress());  // 地址
           System.out.println(inetAddress4.getCanonicalHostName());    // 规范的名字
           System.out.println(inetAddress4.getHostAddress());  // ip
           System.out.println(inetAddress4.getHostName()); // 域名

      } catch (UnknownHostException e) {
           e.printStackTrace();
      }
  }
}

端口

端口表示计算机上的一个程序的进程

  • 端口不能冲突
  • 被规定 0 ~ 665535
  • TCP,UDP:65535 * 2
  • 端口分类
    • 共有端口 0 ~ 1023

      • HTTP:80
      • HTTPS:443
      • FTP:21
      • Telent:23
    • 程序注册端口:1024 ~ 49151

      • Tomcat:8080
      • MySQL:3306
      • Oracle:1512
    • 动态、私有端口:49152 ~ 65535

      1
      2
      3
      netstat -ano   # 查看所有的端口
      netstat -ano | findster "port"    # 查看指定端口
      tasklist | findster “ipd”   # 查看指定端口的进程
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      package com.lesson01;

      import java.net.InetSocketAddress;

      public class TestInetSocketAddress {
         public static void main(String[] args) {
             InetSocketAddress socketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
             InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);

             System.out.println(socketAddress1);
             System.out.println(socketAddress2);

             System.out.println(socketAddress1.getAddress());
             System.out.println(socketAddress1.getHostName());   // 地址
             System.out.println(socketAddress1.getPort());   // 端口

        }
      }

通信协议

TCP/IP协议簇

  • TCP:用户传输协议
  • UDP用户数据报协议
  • IP:网络互连协议

TCP UDP 对比

TCP:(打电话)

  • 连接,稳定
  • 三次握手 四次挥手
  • 客户端、服务端
  • 传输完成,释放连接,效率低

UDP:(发短信)

  • 不连接,不稳定
  • 客户端、服务端:没有明确的界限

TCP

客户端

  1. 连接服务器Socket
  2. 发送消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.lesson02;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

// 客户端
public class TCPClientDemo01 {
   public static void main(String[] args) {

       Socket socket = null;
       OutputStream outputStream = null;

       try {
           // 1.获取服务器地址
           InetAddress serverIP = InetAddress.getByName("127.0.0.1");
           // 端口号
           int port = 9999;

           // 2.创建一个socket连接
           socket = new Socket(serverIP, port);

           // 3.发送消息 IO流
           outputStream = socket.getOutputStream();
           outputStream.write("hello world".getBytes());

      } catch (Exception e) {
           e.printStackTrace();
      } finally {
           if (outputStream != null) {
               try {
                   outputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }

          }

           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

服务端

  1. 建立服务的端口 ServerSocket
  2. 等待客户端的连接 accept
  3. 接收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.lesson02;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

// 服务端
public class TCPServerDemo01 {
   public static void main(String[] args) {

       ServerSocket serverSocket = null;
       Socket socket = null;
       InputStream inputStream = null;
       ByteArrayOutputStream byteArrayOutputStream = null;

       try {
           // 1.创建地址
           serverSocket = new ServerSocket(9999);

           // 2.等待客户端连接
           socket = serverSocket.accept();

           // 3.读取客户端的消息
           inputStream = socket.getInputStream();
           // 管道流
           byteArrayOutputStream = new ByteArrayOutputStream();
           byte[] buffer = new byte[1024];
           int len;
           while ((len = inputStream.read(buffer)) != -1) {
               byteArrayOutputStream.write(buffer, 0, len);
          }
           System.out.println(byteArrayOutputStream.toString());

      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           // 关闭资源

           if (byteArrayOutputStream != null) {
               try {
                   byteArrayOutputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }

           if (inputStream != null) {
               try {
                   inputStream.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }

           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }

           if (serverSocket != null) {
               try {
                   serverSocket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }


      }
  }
}

文件上传

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.lesson02;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServerDome02 {
   public static void main(String[] args) throws IOException {
       // 创建服务
       ServerSocket serverSocket = new ServerSocket(9000);
       // 监听客户端连接
       Socket socket = serverSocket.accept();  // 阻塞式监听。=,会一直等待客户端连接
       // 获取输入流
       InputStream is = socket.getInputStream();

       // 文件输出
       FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
       byte[] buffer = new byte[1024];
       int len;
       while ((len = is.read(buffer)) != -1) {
           fos.write(buffer, 0, len);
      }

       // 通知客户端
       OutputStream os = socket.getOutputStream();
       os.write("ok gad".getBytes());

       // 关闭
       fos.close();
       is.close();
       socket.close();
       serverSocket.close();
  }
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.lesson02;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class TCPClientDome02 {
   public static void main(String[] args) throws IOException {

       // 1. 创建一个Socket连接
       Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);

       // 2. 创建一个输出流
       OutputStream os = socket.getOutputStream();

       // 读取文件
       FileInputStream fis = new FileInputStream(new File("hyd.JPG"));
       // 写文件
       byte[] buffer = new byte[1024];
       int len;
       while ((len = fis.read(buffer)) != -1) {
           os.write(buffer, 0, len);
      }

       // 通知服务器结束
       socket.shutdownOutput();    // 传输完毕

       // 确定服务器接收完毕,断开连接
       InputStream inputStream = socket.getInputStream();
       // String byte[]
       ByteArrayOutputStream baos = new ByteArrayOutputStream();

       byte[] buffer2 = new byte[1024];
       int len2;
       while ((len2 = inputStream.read(buffer2)) != -1) {
           baos.write(buffer2, 0, len2);
      }
       System.out.println(baos.toString());

       // 关闭资源
       baos.close();
       inputStream.close();
       fis.close();
       os.close();
       socket.close();
  }
}

Tomcat

服务端

  • 自定义 S
  • Tomcat服务器

客户端

  • 自定义 C
  • 浏览器 B

UDP

不用连接,需要知道对方对的地址

发送消息

** 发送端**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.lesson03;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

// 不需要连接服务器
public class UDPClientDemo01 {
   public static void main(String[] args) throws IOException {
       // 1. 建立一个Socket
       DatagramSocket socket = new DatagramSocket();

       // 2. 建个包
       String msg = "hello UDP";

       // 发送地址
       InetAddress localhost = InetAddress.getByName("localhost");
       int port = 9090;

       // 数据,数据的长度起始,要发送给谁
       DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);

       // 3. 发送包
       socket.send(packet);

       // 关闭流
       socket.close();
  }
}

** 接收端**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.lesson03;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPServerDome01 {
public static void main(String[] args) throws IOException {
// 开放端口
DatagramSocket socket = new DatagramSocket(9090);

// 接收数据包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);

socket.receive(packet); // 阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(), 0, packet.getLength()));

// 关闭连接
socket.close();
}
}

UPD聊天实现

** 发送端**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UDPSenderDemo01 {
public static void main(String[] args) throws Exception {
//获取连接
DatagramSocket socket = new DatagramSocket(8080);
while (true) {
//准备数据
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket
(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
//发送数据
socket.send(packet);
if (data.equals("bye")) {
break;
}
}

socket.close();


}
}

** 接收端**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.chat;

import java.net.*;

public class UDPReceiveDome01 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);//阻塞式接收包裹


byte[] data = packet.getData();
String receiveData = new String(data, 0, packet.getLength());

System.out.println(receiveData);

//断开连接 bye
if (receiveData.equals("bye")) {
break;
}
}
socket.close();
}
}

多线程在线对话

发送端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class TalkSend implements Runnable {

DatagramSocket socket = null;
BufferedReader reader = null;

private int fromPort;
private String toIP;
private int toPort;

public TalkSend(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;

try {
socket = new DatagramSocket(fromPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}

}


@Override
public void run() {
while (true) {
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort));

socket.send(packet);

if (data.equals("bye")) {
break;
}

} catch (Exception e) {
e.printStackTrace();
}
}
socket.close();
}
}

接收端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class TalkReceive implements Runnable {

DatagramSocket socket = null;
private int port;

public TalkReceive(int port) {
this.port = port;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}

@Override
public void run() {
while (true) {
try {
//准备接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);//阻塞式接收包裹


byte[] data = packet.getData();
String receiveData = new String(data, 0, packet.getLength());

System.out.println(packet.getPort() + ": " + receiveData);

//断开连接 bye
if (receiveData.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}

发起对话

1
2
3
4
5
6
7
8
package com.chat;

public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7777, "localhost", 9999)).start();
new Thread(new TalkReceive(8888)).start();
}
}

接收对话

1
2
3
4
5
6
7
8
package com.chat;

public class TalkStudent {
public static void main(String[] args) {
new Thread(new TalkSend(7777, "localhost", 9999)).start();
new Thread(new TalkReceive(8888)).start();
}
}

URL

统一资源定位符:定位资源的,定位互联网上的某一个资源

1
协议://ip地址:端口号/项目名/资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.lesson04;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class URLDown {
   public static void main(String[] args) throws IOException {

       // 下载地址
       URL url = new URL("https://pica.zhimg.com/80/v2-6257d94a8a01c48fe57e6e6c4456c8ac_720w.jpg?source=1940ef5c");

       // 连接资源 HTTP
       HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

       InputStream inputStream = urlConnection.getInputStream();

       FileOutputStream fos = new FileOutputStream("v2-6257d94a8a01c48fe57e6e6c4456c8ac_720w.jpg");

       byte[] buffer = new byte[1024];
       int len;
       while ((len = inputStream.read(buffer)) != -1) {
           fos.write(buffer, 0, len);
      }
       fos.close();
       inputStream.close();
       urlConnection.disconnect(); // 断开连接


  }
}