第八章 网络编程 v1.0
第一部分 网络通信
一、网络通信基本模式
1.Client-Server(CS)

2.Brower-Server(BS)

二、网络通信三要素
1.IP地址
设备在网络中的地址,是唯一的标识
IPv4:32位(4字节):分为4个整数,使用点分十进制表示
IPv6:128位(16字节):分为8个整数,每个用4个十六进制数表示,用冒号隔开
IP地址操作类(InetAddress)
2.端口号
应用程序在设备中唯一的标识
标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0~65535
常用端口号:HTTP:80;HTTPS:443;FTP:21
3.协议
数据在网络中传输的规则,常见的协议有UDP协议和TCP协议
OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广。
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

第二部分 UDP通信
一、UDP相关API
1.数据包对象(DatagramPacket)
构造函数:
DatagramPacket(byte[] b, int length, InetAddress ip, int port):创建发送端数据包对象DatagramPacket(byte[] b, int length):创建接收端数据包对象
常用方法:
getLength():获得实际接收到的字节个数
2.套接字对象(DatagramSocket)
构造函数:
DatagramSocket():常用于创建发送端Socket对象,系统随机分配一个端口号DatagramSocket(int port):常用于创建接收端Socket对象,指定分配端口号
常用方法:
send(DatagramPacket p):发送数据包receive(DatagramPacket p):接收数据包
二、发送端与服务端
1.发送端
public class Server {
public static void main(String[] args) throws Exception {
//创建发送端对象
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
String input;
while (!Objects.equals(input = sc.nextLine(), "exit")) {
byte[] buffer = input.getBytes();
//创建数据包(指定长度,发送IP地址与端口)
DatagramPacket packet = new DatagramPacket(buffer,
buffer.length,
InetAddress.getLocalHost(),
8888);
//发送数据包
socket.send(packet);
}
socket.close();
}
}2.服务端
public class Client {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(8888);
byte[] buffer = new byte[1024 * 64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
socket.receive(packet);
System.out.println(new String(buffer, 0, packet.getLength()));
}
}
}三、UDP三种通信方式
1.单播
单台主机与单台主机之间的通信
2.广播
当前主机与所在网络中的所有主机通信,广播地址:255.255.255.255
发送端:发送的数据包的目的地写的是广播地址(255.255.255.255)、且指定端口。
接收端:所在网段的其他主机的程序只要匹配端口成功即就可以收到消息了。
3.组播
当前主机与选定的一组主机的通信,组播地址:224.0.0.0~239.255.255.255
发送端:数据包的目的地是组播IP(224.0.0.1~239.255.255.255)
接收端:必须绑定该组播IP,端口对应发送端的目的端口,即可接收该组播消息
//接收端
MulticastSocket socket = new MulticastSocket(8888); //DatagramSocket的子类
socket.joinGroup(InetAddress.getByName("224.0.0.1")); //绑定组播IP第三部分 TCP通信
一、套接字对象
1.发送端(客户端)
构造方法:
Socket(String host, int port):创建一个发送消息的TCP对象,指定连接端口
常用方法:
getOutputStream():从通信管道中得到一个字节输出流(对应发送端)
getInputStream():从通信管道中得到一个字节输入流(对应接收端)
2.接收端(服务端)
构造方法:
ServerSocket(int port):构建一个用于构建接收的TCP连接的对象的对象
常用方法:
accept():由该对象生成Socket对象
3.基本概念
- 客户端怎么发,服务端就应该怎么收,客户端如果没有消息,服务端会进入阻塞等待。
- Socket一方关闭或者出现异常、对方Socket也会失效或者出错。
二、构建TCP连接
1.示例(点对点)
public class Client {
public static void main(String[] args) throws Exception {
try (
Socket socket = new Socket("127.0.0.1", 5000);
) {
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
String s;
Scanner sc=new Scanner(System.in);
while(true){
s=sc.nextLine();
ps.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}public class Server {
public static void main(String[] args) throws Exception {
try (
ServerSocket serverSocket=new ServerSocket(5000);
) {
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
BufferedReader bs = new BufferedReader(new InputStreamReader(is));
String msg;
while((msg=bs.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+":"+msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}2.服务端处理多个客户端消息
单线程每次只能处理一个客户端的Socket通信,需要引入多线程(线程池)优化
public class Server {
static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws Exception {
try (
ServerSocket serverSocket = new ServerSocket(5000);
) {
while (true) {
Socket socket = serverSocket.accept();
System.out.println(socket.getRemoteSocketAddress() + ":上线了");
Runnable target = new ServerReaderRunnable(socket);
pool.execute(target);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ServerReaderRunnable implements Runnable {
Socket socket;
ServerReaderRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader bs = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg = bs.readLine()) != null) {
System.out.println(socket.getRemoteSocketAddress() + ":" + msg);
}
} catch (java.net.SocketException ignored) {
} catch (Exception e) {
e.printStackTrace();
}
}
}3.即时通信
即时通信,即指一个客户端的消息发出去,其他客户端可以接收到
即时通信需要进行端口转发的设计思想,服务端需要把在线的Socket管道存储起来,一旦收到一个消息要推送给其他管道