1、软件架构
先来了解一下软件架构:B/S与C/S。
B/S:Brower/Server,即浏览器与服务器。
C/S:Client/Server,则是客户端与浏览器
B/S与C/S的联系与区别:
(1)联系:都分为前端(页面展示)和后台(业务逻辑开发)。
(2)区别:
①B/S需开发一个网页,在浏览器打开;C/S则需要再单独开发一个客户端程序,而且要下载和安装。
②B/S每次更新什么新功能时,用户只需在浏览器刷新一下就好了。而C/S每次版本更新时用户都需要重新下载安装客户端。
③B/S图片和音乐都不是很精美,因为需要通过网络从服务器传过来。而C/S图片和音乐都很精美,因为已经下载到本地了。
2、数据传输三要素
(1)设备的地址:IP
(2)哪个软件:端口号
(3)数据传输的协议:UDP、TCP
当进行数据传输时,需要知道发送到哪个电脑上,以及电脑上的哪个软件上去,以及用哪种协议进行数据传输。
3、IP
首先来介绍一下IP的格式:
(1)IPv4
IPv4可表示的设备地址总共有256*256*256*256=4,294,967,296个。
在2019年11月16日就已经使用完毕,后面又引入了地址转换技术,解决了地址枯竭问题。即将网络分为内网和外网,外网是真实分配的IP地址,是不能重复的,而内网是自行分配的IP地址,不同的内网之间是可以重复的。
(2)IPv6
由于IPv4不够用的问题,又设计了IPv6。
(3)那么在Java中如何表示IP呢?
Java中提供了一个InetAddress类用来表示IP。
如何获取InetAddress的对象?
方法名 | 说明 |
---|---|
static InetAddress getByName(String host) | 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 |
①静态方法getByName(String str)会自动根据系统使用的IP来返回对应的IP对象。
②参数既可以传递主机名,也可以传递IP地址。
常用方法:
方法名 | 说明 |
---|---|
String getHostName() | 获取此IP地址的主机名 |
String getHostAddress() | 返回文本显示中的IP地址字符串 |
4、端口
给软件绑定一个数字,使得传递的信息可以找到哪个软件。
5、UDP
面向无连接的数据传输方式,就是只管发,根本不管对方能不能收到。
如何使用UDP进行数据的发送和接收?
(1)数据的发送:
①创建UDP对象(DatagramSocket)
发送需要有端口号,既可以自己指定,也可以程序从可用的端口号中随机选取一个。
②把数据封装成DatagramPacket对象
还需表明向哪个IP的哪个端口发送信息。
③发送数据
④释放资源
代码实现如下:
public class sendMessage {
public static void main(String[] args) throws IOException {
//1.创建快递公司对象
//既可以传递参数,也可以是无参
//无参表示从可使用的端口中随机选择一个
//有参则是指定一个端口号
DatagramSocket ds = new DatagramSocket();
//2.打包数据
String str = "nihao";
byte[] bytes = str.getBytes();
InetAddress ip = InetAddress.getByName("127.0.0.1");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,port);
//3.发送数据
ds.send(dp);
//4.释放资源
ds.close();
}
}
(1)数据的接收:
①创建UDP对象(DatagramSocket)
一定要绑定端口号,表示从哪个端口接收数据。
②把接收到的数据放到DatagramPacket对象
③接收数据
④释放资源
代码实现如下:
public class receiveMessage {
public static void main(String[] args) throws IOException {
//一定要绑定端口号
//表示从哪个端口接收数据
DatagramSocket ds = new DatagramSocket(10086);
//创建一个包用来接收数据
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//进行接收
ds.receive(dp);
//解析数据
byte[] data = dp.getData();
String str = new String(data);
InetAddress address = dp.getAddress();
int port = dp.getPort();
System.out.println("接收到的数据为:"+str + ",由ip为" + address + ",端口号为" + port + "进行发送");
//释放资源
ds.close();
}
}
细节: receive方法是阻塞的,就是程序会停在这一步,等发送的数据,只有接收到数据时才会结束。
可以看到:
UDP的3种通信方式:单播、组播、广播。
和之前的IP地址有什么区别呢?
之前的IP地址表示一个IP,而组播地址可以表示一组IP。
问题:
代码如下,但是只能输出一部分数据。
为什么输出的数据只有一部分呢?不知道。
改成这种格式试一下:
可以看到就能完整地输出了,不知道为什么。
6、TCP
面向连接的数据传输,即在传输之前必须确保连接已经建立,连接建立完成之后使用IO流进行传输。
(1)发送端的代码实现:
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10086);
OutputStream os = socket.getOutputStream();
os.write("你好呀".getBytes());
os.close();
socket.close();
}
}
(2)接收端的代码实现:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10086);
Socket socket = ss.accept();
InputStream is = socket.getInputStream();
int b;
while((b = is.read()) != -1) {
System.out.print((char)b);
}
}
}
运行结果,可以看到输出是乱码的:
因为使用字节流读取中文会乱码,所以可以使用转换流转换为字符流读取。
2个细节:
①先运行服务端,然后监听有没有客户端建立连接 ,建立了连接之后就可以进行数据传输了。
②客户端在释放资源的时候,要确保通道中的数据已经被服务端接收完毕才可以。
(3)3次握手
(4)4次挥手
确保数据传输完毕,断开连接。
客户端:今天就到这吧 服务器:好,我收拾一下 服务器:我收拾完了 客户端:OK,退房。