网络编程
day26 01-网络编程(网络模型概述)
1、网络所涵盖的东西很多,为了方便于理解,也为了方便于建设。人们把他们划分成了不同的层次,每一层都有不同的功能。
2、网络模型:OSI(OpenSystem Interconnection 开放系统互连)参考模型(7层)
TCP/IP参考模型(7层太麻烦,简化为4层)
3、7层概述
①物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
②数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
③网络层:主要将下层接收到的数据进行IP地址(例,192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
④传输层:定义了一些传输数据的协议和端口号(WWW端口号80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层叫做段。
⑤会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接收会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。
⑥表示层:主要是进行对接收的数据进行解释,加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够识别的东西(如图片、声音等)。
⑦应用层:主要是一些终端的应用,比如说FTP(各种文件下载)、WEB(IE浏览)、QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西,就是终端应用)。
4、画图说说这7层
day26 02-网络编程(网络要素1-IP地址)
1、网络通讯要素:①IP地址②端口号③传输协议
2、IP地址:要想通讯,我得先找到你。我想找你,那得有标识。对于计算机而言,这个标识就是IP地址。IP地址,类似于192.168.1.100,都由这4段数据组成。每一段都是字节,他每一段能取的最大数据就是255.
3、现在IP地址逐渐不够用了。后期有了IPV6版本。这个版本融入了字母,排列就变多了。另外注意,IP地址可不止计算机能分配。物联网!
4、IP地址:InetAddress
网络中设备的标识。
不易记忆,可用主机名。
本地回环地址:127.0.0.1 主机名:localhost。
5、何为本地回环地址(127.0.0.1)?
你机子没联网,但想访问本机。他给你弄了这么一个默认的。你在cmd中ping 127.0.0.1可以测试网卡。这挂了,有可能就是网卡挂了。
day26 03-网络编程(网络要素2-端口)
1、端口号:用于标识进程的逻辑地址。是不同进程的标识。
2、有效端口:0-65535。其中0-1024为系统使用或保留端口,所以这几个尽量不要用。
3、为了进行这些应用程序的标识区分,他这里面就提供了一些数字(进程编号)
这些数字就是端口。机箱上的那叫物理端口(看得见,摸得着);而这个叫做逻辑端口,是给应用程序分配的数据标识。
4、360安全卫士——功能大全——网络连接查看器
5、防火墙:其功能就是将发送到某程序端口的数据屏蔽掉以及将从该程序端口发出的数据也屏蔽掉。比如QQ端口是4000,你将4000发来的数据全部禁掉,将4000发出的数据全禁掉。这就叫防火墙。
day26 04-网络编程(网络要素3-传输协议)
1、传输协议:通讯的规则。常见的协议:TCP(传输控制协议),UDP(数据报文协议)。
2、UDP协议
将数据及源和目的封装到数据报包中,不需要建立连接。
每个数据报包的大小限制在64K以内。
因为无连接,是不可靠协议。
不需要建立连接,速度快。
应用案例:QQ、FeiQ聊天、在线视频用的都是UDP传输协议。
3、UDP类似于寄包裹,对讲机。
4、TCP协议
建立连接,形成传输数据的通道。(没连接就不通讯)
在连接中进行大数据量传输。
通过3次握手完成连接,是可靠协议。
必须建立连接,效率会稍低。
应用案例:FTP,File Transfer Protocol(文件传输协议)。
5、3次握手图解:
6、TCP类似于打电话
day26 05-网络编程(IP对象-InetAddress)
1、IP地址在网络通讯要素中比较复杂。所以,在java中,它本身也被封装成了对象。
2、类InetAddress:此类表示互联网协议(IP)地址
方法摘要 | |
| |
| getAddress |
| getAllByName |
| getByAddress |
| getByAddress |
| |
getCanonicalHostName | |
getHostAddress | |
getHostName | |
| getLocalHost |
| hashCode |
| isAnyLocalAddress |
| isLinkLocalAddress |
| isLoopbackAddress |
| isMCGlobal |
| isMCLinkLocal |
| isMCNodeLocal |
| isMCOrgLocal |
| isMCSiteLocal |
| isMulticastAddress |
| isReachable |
| isReachable |
| isSiteLocalAddress |
toString |
3、InetAddress没有构造函数,但是他还有非静态方法。说明应该有方法返回其对象。
4、代码示例1——获取本地主机信息
public class Inet {
public static void main(String[] args) throws Exception {
//获取本地主机IP地址对象
InetAddress ip = InetAddress.getLocalHost();
//打印主机的IP地址
System.out.println(ip.getHostAddress());
//打印主机名
System.out.println(ip.getHostName());
}
}
运行结果:169.254.35.90
WINDOWS-STCMIDA
5、代码示例2——获取其他主机信息
public class InetDemo {
public static void main(String[] args) throws IOException {
InetAddress ip = InetAddress.getByName("192.168.0.115");
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());
}
}
6、代码示例3——我去拿百度的ip
public class InetDemo {
public static void main(String[] args) throws IOException {
InetAddress ip = InetAddress.getByName("www.baidu.com");
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());
}
}
运行结果:115.239.211.112
www.baidu.com
7、有些对应的ip地址不唯一。像:新浪、网易,他们的IP地址有可能不唯一。服务器集群。
day26 06-网络编程(域名解析)
1、什么是域名解析,下面通过一个图来理解
凡是访问其他主机,走的必须是ip。那为什么我们写的都是www.sina.com之类的,而不是10.1.1.1呢?因为互联网上的主机非常多,IP地址也非常多。我们不可能天天记这些网站的IP地址。
day26 07-网络编程(UDP协议-发送端)
1、Socket:Socket就是为网络服务提供的一种机制。通讯的两端都有Socket(网络服务端点)。网络通信其实就是Socket之间的通讯。数据在两个Socket间通过IO传输。Socket可以理解为通讯的两端。
2、Socket就像是港口。
3、UDP传输
DatagramSocket(用来发送和接收数据报包的套接字)与DatagramPacket(数据报包)。
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
发送端与接收端是两个独立的运行程序。
4、类DatagramSocket:此类表示用来发送和接收数据报包的套接字
构造方法摘要 | |
| DatagramSocket |
| DatagramSocket |
| DatagramSocket |
| DatagramSocket |
| DatagramSocket |
方法摘要 | |
| receive |
| close |
| send |
5、类DatagramPacket
此类表示数据报包。数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息,从一台机器路由到另一台机器。不对包投递做出保证。
构造方法摘要 | |
DatagramPacket | |
DatagramPacket | |
DatagramPacket | |
DatagramPacket | |
DatagramPacket | |
DatagramPacket |
方法摘要 | |
getAddress | |
| getData |
| getLength |
| getOffset |
| getPort |
getSocketAddress | |
| setAddress |
| setData |
| setData |
| setLength |
| setPort |
| setSocketAddress |
6、UDP按照包往外发,包本身也是对象。
7、包在构造时,有的包是用来接收数据的,有的包是用来封装发送的数据的。最明显的区别,用于存储发送的数据的数据包,他们里面有目的地址。而接收不需要。凡是带着ip对象的,都是用来发送的。
8、创建UDP传输的发送端。
思路:①建立UDP的Socket服务。
②将要发送的数据封装到数据包中。
③通过udp的Socket服务将数据包发出去。
④关闭Socket服务。
9、代码示例——UDP发送端
public class UDPDemo {
public static void main(String[] args) throws Exception {
//1、udpSocket服务,使用DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//2、将要发送的数据封装到数据报包中
String str = "udp传输演示";
byte[] buf = str.getBytes();
DatagramPacketdp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);
//3、通过udp的Socket服务将数据包发送出去。使用send方法
ds.send(dp);
//4、关闭资源
ds.close();
}
}
10、发送端搞定
day26 08-网络编程(UDP协议-接收端)
1、建立UDP接收端的思路
①建立Socket服务。
②创建数据包,用于存储接收到的数据。方便用数据包对象的方法解析这些数据。
③使用Socket服务的receive方法将接收到的数据存储到数据包中。
④通过数据包的方法解析数据包中的数据。
⑤关闭资源。
2、代码示例——UDP接收端
public class UDPDemo2 {
public static void main(String[] args) throws Exception {
//1、建立udp Socket服务
DatagramSocket ds = new DatagramSocket(10000); //接收端在建立Socket服务的时候必须明确一个端口号
//2、创建数据报包
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3、使用接收方法将数据存储到数据报包中
ds.receive(dp);
//4、通过数据报包对象的方法,解析其中的数据。比如:地址、端口、数据内容
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = newString(buf,0,dp.getLength());
System.out.println(ip+":"+port+":"+text);
}
}
3、先运行接收端,在运行发送端,运行结果:127.0.0.1:1219:udp传输演示
day26 09-网络编程(UDP协议-聊天程序)
1、聊天程序需要读取键盘录入
2、代码示例——UDP聊天程序发送端
public class UDPDemo3 {
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line = bufr.readLine())!=null){
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);
ds.send(dp);
if("88".equals(line)){
break;
}
}
ds.close();
}
}
3、代码示例——UDP聊天程序接收端
public class UDPDemo04 {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10000);
byte[] buf = new byte[1024];
while(true){
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
Stringip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = newString(dp.getData(),0,dp.getLength());
System.out.println(ip+":"+port+":"+text);
if("88".equals(text)){
break;
}
}
}
}
4、但是上面两个程序还是俩窗口,我们搞成一个窗口。即开两个线程。
5、代码示例——UDP单窗口收发数据——多线程
public class UDPDemo05 {
public static void main(String[] args) throws SocketException {
DatagramSocket ds1 = new DatagramSocket();
DatagramSocket ds2 = new DatagramSocket(10000);
UdpSend send = new UdpSend(ds1);
UdpRece rece = new UdpRece(ds2);
new Thread(send).start();
new Thread(rece).start();
}
}
class UdpSend implements Runnable{
DatagramSocket ds;
public UdpSend(DatagramSocket ds){
this.ds = ds;
}
public void run(){
try{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line =bufr.readLine())!=null){
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);
ds.send(dp);
if("88".equals(line)){
break;
}
}
ds.close();
}catch(Exception e){
}
}
}
class UdpRece implements Runnable{
DatagramSocket ds;
public UdpRece(DatagramSocket ds){
this.ds = ds;
}
public void run(){
try{
while(true){
byte[] b = new byte[1024];
DatagramPacket dp =new DatagramPacket(b,b.length);
ds.receive(dp);
String ip =dp.getAddress().getHostAddress();
int port = dp.getPort();
String text = newString(b,0,dp.getLength());
System.out.println(ip+":"+port+":"+text);
if("88".equals(text)){
break;
}
}
}catch(Exception e){
}
}
}
6、聊天室搞好了,但是这只能单聊,不能群聊。想群聊,怎么办?发广播!
一个网段中,有效地址是1-254。0不能用,0代表网络位,代表192.168.1这个网段。255不是IP地址,是广播地址。如果你敢把信息发给192.168.1.255的话,那就意味着这个信息会发到192.168.1这个网段所有存活的机器上。所以,你想发广播,只需要把UdpSend类中的DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10000);
改为:
DatagramPacketdp = new DatagramPacket(buf,buf.length,InetAddress.getByName(“192.168.1.255”),10000);
就能广播了。
day26 10-网络编程(TCP协议-客户端)
1、TCP传输
Socket(客户端)和ServerSocket(服务端)
建立客户端和服务端
建立连接后,通过Socket中的IO流进行数据的传输。
关闭Socket流。
同样,客户端与服务端是两个独立的应用程序。
2、图解
客户端(Client)首先与服务端(Server)建立连接,形成通道(其实就是IO流),然后,数据就可以在通道之间进行传输,并且单个Server端可以同时与多个Client端建立连接。
3、类Socket
此类实现客户端套接字。
4、类ServerSocket
此类实现服务端套接字。
5、我们讲到客户端服务端,一定是TCP传输。讲到发送端接收端,一定是UDP传输。
6、TCP传输,客户端建立的过程
①创建TCP客户端Socket服务。使用的是Socket对象。
建议该对象一创建就明确目的地——要连接的主机。
②如果连接建立成功,就说明数据传输通道已经建立。该通道就是Socket流。可以通过Socket对象的getOutputStream方法getInputStream方法获取两个字节流。
③若是客户端发数据到服务端,使用输出流,将数据写出。
④关闭资源。
7、代码示例——TCP客户端
public class TCPDemo1 {
public static void main(String[] args) throws Exception {
//1、创建客户端Socket服务
Socket socket = new Socket("127.0.0.1",10000);
//2、获取Socket流中的输出流
OutputStream out =socket.getOutputStream();
//3、使用输出流将指定的数据写出去
out.write("tcp演示".getBytes());
//4、关闭资源(其实是将连接断开)
socket.close();//流out不用关,你把Socket干掉了,这流也就没有了
}
}
day26 11-网络编程(TCP协议-服务端)
1、建立TCP服务端的思路
①创建服务端Socket服务。通过ServerSocket对象。
②服务端必须对外提供一个端口,否则客户端无法连接。
③获取连接过来的客户端对象。
④通过客户端对象Socket获取流,读取客户端发来的数据。
⑤关闭资源(注意,这个服务端的资源应该关闭两个,客户端、服务端)
2、需求:服务端接收客户端发送过来的数据,并且打印在控制台上。
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1、创建服务端对象
ServerSocket ss = new ServerSocket(10000);
//2、获取连接过来的客户端对象
Socket s = ss.accept();
//3、通过Socket对象获取输入流,要读取客户端发来的数据
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String ip = s.getInetAddress().getHostAddress();
int port = s.getPort();
String text = new String(buf,0,len);
System.out.println(ip+":"+port+":"+text);
s.close();
}
}
3、先运行服务端,再运行客户端,运行结果:127.0.0.1:24970:TCP演示
day26 12-网络编程(TCP协议-服务端和客户端交互)
1、接下来我们把客户端和服务端深化一下,我既能用客户端收,也能用客户端反馈。
2、代码示例——客户端能发能收
public class ClientDemo01 {
public static void main(String[] args) throws UnknownHostException,IOException {
Socket s = new Socket("127.0.0.1",10000);
OutputStream out = s.getOutputStream();
out.write("tcp传输".getBytes());
//读取客户端返回的数据,使用Socket读取流
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
//关闭资源
s.close();
}
}
3、代码示例——服务端能发能收
public class ServerDemo01 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf,0,len);
System.out.println(text);
//使用客户端Socket对象的输出流给客户端返回数据
OutputStream out = s.getOutputStream();
out.write("收到".getBytes());
s.close();
}
}
4、先运行服务端,再运行客户端,运行结果:
哦了
day26 13-网络编程(TCP协议-练习-文本转换客户端)
1、需求:客户端输入字母数据,发送给服务端。服务端收到后显示在控制台上,并将该数据转成大写返回给客户端。指导客户输入over,转换结束。说白了,就是创建一个英文大写转换服务器。
2、思路:客户端
①需要先有Socket端点
②客户端的数据源:键盘
③客户端的目的:Socket
④接受服务端的数据:源:Socket
⑤将数据显示打印出来:目的地:控制台
⑥在这些流中操作的数据,都是文本数据
3、代码示例——文本转换客户端
public class ClientDemo02 {
public static void main(String[] args) throws UnknownHostException,IOException {
//1、创建Socket客户端对象
Socket socket = new Socket("127.0.0.1",10000);
//2、获取键盘录入
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//3、Socket输出流(将数据发送到服务端)
PrintWriter out = newPrintWriter(socket.getOutputStream(),true);
//4、socket输出流,读取服务端返回的大写数据(接收服务端数据)
BufferedReader bufIn = new BufferedReader(newInputStreamReader(socket.getInputStream()));
String line = null;
while((line = bufr.readLine())!=null){
if("over".equals(line)){
break;
}
//将数据发送到客户端
out.println(line);
//读取服务端返回的一行大写数据
String upperStr = bufIn.readLine();
//将服务端返回的数据打印到控制台上
System.out.println(upperStr);
}
socket.close();
}
}
day26 14-网络编程(TCP协议-练习-文本转换服务端)
1、转换的服务端思路:
①ServerSocket服务
②获取Socekt对象
③源:Socket,读取客户端发过来的需要转换的数据
④目的:显示在控制台上
⑤将数据转成大写,发给客户端
2、代码示例——文本转换服务端
public class ServerDemo02 {
public static void main(String[] args) throws IOException {
//1、ServerSocket服务
ServerSocket server = new ServerSocket(10000);
//2、获取Socket对象
Socket s = server.accept();
//3、获取Socket读取流,并装饰(读取从客户端发来的数据)
BufferedReader bufIn = new BufferedReader(newInputStreamReader(s.getInputStream()));
//4、获取Socket的输出流,并装饰(将数据发送到客户端)
PrintWriter out = newPrintWriter(s.getOutputStream(),true);
String line = null;
while((line =bufIn.readLine())!=null){
//将从客户端读到的数据打印在控制台上
System.out.println(line);
//将数据转换成大写,并发送给客户端
out.println(line.toUpperCase());
}
s.close();
}
}
3、 先运行文本转换服务端,再运行文本转换客户端。运行结果:
哦了