目录
一、网络编程入门
1.软件结构
2.网络通信协议
编辑 3.协议分类
4.网络编程要素
IP地址
IP地址分类
常用命令
特殊的IP地址
InetAddress 类
常用方法
端口号
二、UDP协议编程
DatagramSocket类
构造方法
常用方法
DatagramPacket类
构造方法
常用方法
使用UDP通信
UDP三种通讯方式
UDP组播实现
UDP广播实现
三、TCP通信程序
Socket 类
构造方法
C/S结构:全称为Client/Server结构,是指客户端和服务端结构。常见程序有QQ、迅雷等软件。
B/S结构:全程为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。
两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的
协议下,实现两台计算机的通信的程序。
通信协议是对计算计必须遵守的规则,只有遵守这些规则,计算机之间才能进行通信。这
就好比在道路中行驶的汽车一定要遵守交通规则一样,协议中对数据的传输格式、传输速
率、传输步骤等做了统一规定,通信双方必须同时遵守,最终完成数据交换。
通信的协议还是比较复杂的,java.net包中的类和接口,他们提供低层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
java.nei包中提供两种常见的网络协议的支持:
完成三次握手,建立连接后,客户端和服务器就可以开始进行数据传输了。由于这种面向
连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏
览网页等。
补充:三次握手和四次挥手
建立连接(三次握手):
协议、IP地址、端口号。
互联网协议地址,俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
IPv4:是一个32位的二进制数,通常被分为四个字节,表示为a.b.c.d的形式,例如192.168.1.66。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。
IPv6:为了互联网的蓬勃发展,IP地址的需求量越来越大,但是网络地址资源有限,使得IP的分配愈发紧张。有资料显示,全球IPv4地址在2011年2月分配完毕。为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成 ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 ,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。
ipconfi
ping 空格 IP地址
区别:
1. localhost 等于 127.0.0.1 ,不过 localhost 是域名, 127.0.0.1 是 IP 地址。
2. localhost 和 127.0.0.1 不需要联网,都是本机访问
3. 本机 IP 需要联网,本机 IP 是本机或外部访问, 本机 IP 就是本机对外放开访问的 I
P 地址,这个网址就是与物理网卡绑定的 IP 地址
4. localhost 是一个域名,在过去它指向 127.0.0.1 这个IP地址。在操作系统支持 ipv6
后,它同时还指向ipv6 的地址 ::1
java.net.InetAddress 表示Internet协议( IP )地址。 IP 地址是由 IP 使用的32位或
128位无符号数字,构建 UDP 和 TCP 协议的低级协议。
网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么
在网络通信时,如何区分这些进程呢?
如果说 IP 地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程
(应用程序)了。每个端口同时只能有一个进程使用,端口是计算机与外界通信的入口和
出口。
端口号:用两个字节表示的整数,它的取值范围是 0~65535 。其中, 0~1023 之间的端口
号用于一些知名的网络服务和应用,普通的应用程序需要使用 1024 以上的端口号。如果
端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
利用 协议 + IP地址 + 端口号 三元组合,就可以标识网络中的进程了,那么进程间的通
信就可以利用这个标识与其它进程进行交互。
查看本机端口情况使用 netstat -ano 命令
telnet ip 端口
java.net.DatagramSocket 表示用于发送和接收数据报数据包的套接字,数据报套接字是分
组传送服务的发送或接收点。 DatagramSocket 应该绑定到通配符地址。 在一些实现中,
当 DatagramSocket 绑定到更具体的地址时,也可以接收广播分组。
常用构造方法有:
当此方法返回时, DatagramPacket 的缓冲区将填充接收到的数据。 数据包数据包还包
含发送者的 IP 地址和发件人机器上的端口号。 该方法阻塞,直到接收到数据报。 数
据报包对象的length字段包含接收到的消息的长度。 如果消息长于数据包的长度,消息
将被截断。
java.net.DatagramPacket 表示数据报包,数据报包用于实现无连接分组传送服务。 仅基于
该数据包中包含的信息,每个消息从一台机器路由到另一台机器。
步骤:
1. 【发送端】 创建目标主机发送对象 DatagramSocket
2. 【发送端】 创建发送信息 DatagramPacket 对象
3. 【发送端】 发送端发送信息
4. 【接收端】 创建用于接收信息的 DatagramPacket 对象
5. 【接收端】 创建 DatagramSocket 对象
6. 【接收端】 接收信息
发送端
package network.day3;
import java.io.IOException;
import java.net.*;
/**
* 练习:
* 发送端:发送数据来源于键盘录入,直到输入 end 表示发送结束
* 发送端要写一个专门接收响应的线程,用于接收对方的反馈接收端:死循环接收数据
* 接收端接收到数据后,向发送端指定端口发送一条 接收到信息的反馈
* 发送端发送消息时包含以下部分:
* 1.消息格式(text, mp3,jpg, png,..
* 2.消息内容
* 3.发送时间
* 4.接收回复端口
* 建议包装成jison
*/
public class SendDemo {
public static void main(String[] args) {
try {
//发送数据报
DatagramSocket socket = new DatagramSocket();
InetAddress localHost = InetAddress.getByName("WIN-EB2ASK9538P");
int post=8080;
System.out.println(socket.getPort());
System.out.println(socket.getLocalPort());
String s="咕噜咕噜咕噜噜";
DatagramPacket datagramPacket = new DatagramPacket(s.getBytes(), s.getBytes().length, localHost, post);
socket.send(datagramPacket);
System.out.println("发送成功");
socket.close();
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
接收端
package network.day3;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 使用UDP协议接收数据
*/
public class UDPReceive {
public static void main(String[] args) {
//存储接收到的数据
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
try {
DatagramSocket socket = new DatagramSocket(8080);
socket.receive(datagramPacket);
String s = new String(datagramPacket.getData(), 0, datagramPacket.getLength());
System.out.println(datagramPacket.getAddress()+"发送了:"+s);
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
单播用于两个主机之间的端对端通信
组播用于对一组特定的主机进行通信
广播用于一个主机对整个局域网上所有主机上的数据通信
组播地址: 224.0.0.0 ~ 239.255.255.255
其中 224.0.0.0 ~ 224.0.0.255 为预留的组播地址
1. 创建发送端的Socket对象(DatagramSocket)
2. 创建数据,并把数据打包(DatagramPacket)
3. 调用DatagramSocket对象的方法发送数据(在单播中,这里是发给指定IP的电脑但
是在组播当中,这里是发给组播地址)
4. 释放资源
1. 创建接收端Socket对象(MulticastSocket)
2. 创建一个箱子,用于接收数据
3. 把当前计算机绑定一个组播地址
4. 将数据接收到箱子中
5. 解析数据包,并打印数据
6. 释放资源
// 发送端
public class ClinetDemo {
public static void main(String[] args) throws IOException {
// 1. 创建发送端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket();
String s = "hello 组播";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("224.0.1.0");
int port = 10000;
// 2. 创建数据,并把数据打包(DatagramPacket)
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
// 3. 调用DatagramSocket对象的方法发送数据(在单播中,这里是发给指定IP的电脑但是
在组播当中,这里是发给组播地址)
ds.send(dp);
// 4. 释放资源
ds.close();
}
}
// 接收端
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1. 创建接收端Socket对象(MulticastSocket)
MulticastSocket ms = new MulticastSocket(10000);
// 2. 创建一个箱子,用于接收数据
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
// 3. 把当前计算机绑定一个组播地址,表示添加到这一组中.
ms.joinGroup(InetAddress.getByName("224.0.1.0"));
// 4. 将数据接收到箱子中
ms.receive(dp);
// 5. 解析数据包,并打印数据
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data,0,length));
// 6. 释放资源
ms.close();
}
}
广播地址: 255.255.255.255
当数据发送到广播地址时,会把数据发送给所有能连接的计算机
// 发送端
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1. 创建发送端Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket();
// 2. 创建存储数据的箱子,将广播地址封装进去
String s = "广播 hello";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
// 3. 发送数据
ds.send(dp);
// 4. 释放资源
ds.close();
}
}
// 接收端
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1. 创建接收端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket(10000);
// 2. 创建一个数据包,用于接收数据
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
// 3. 调用DatagramSocket对象的方法接收数据
ds.receive(dp);
// 4. 解析数据包,并把数据在控制台显示
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data,0,length));
// 5. 关闭接收端
ds.close();
}
}
TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)
与服务端(Server)。
Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,
并通过Socket产生IO流来进行网络通信。
Java为客户端提供了Socket类,为服务器端提供了ServerSocket类。
两端通信时步骤:
1.客户端: java.net.Socket 类表示。创建 Socket 对象,向服务端发出连接请
求,服务端响应请求,两者建立连接开始通信。
2.服务端: java.net.ServerSocket 类表示。创建 ServerSocket 对象,相当于开启
一个服务,并等待客户端的连接。
Socket 类 :该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。
public class Socket implements java.io.Closeable
常用的构造方法是:
//创建流套接字并将其连接到指定主机上的指定端口号,如果指定的主机是null ,则相当于指定地址为
InetAddress.getByName (null) 。 换句话说,它相当于指定回送接口的地址
public Socket(String host, int port)
回送地址(127.x.x.x) 是本机回送地址(Loopback Address),主要用于网络软件测试
以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不
进行任何网络传输。