网络编程是为了让计算机直接或间接地通过网络与其他计算机进行通讯
一、网络模型
1.OSI模型
OSI全称是open system interconnection,即开放系统互连模型。
OSI模型将网络通信过程划分为七个层次,从下到上依次为物理层、数据链路层、网络层、传输
层、会话层、表示层和应用层。
OSI是一个理想化的标准模型
OSI参考模型:
2.TCP/IP
TCP全称是transmission control protocol,即传输控制协议。IP全称是Internet protocol,即因特网互联协议。TCP/IP将网络通信过程划分为网络接口层、网络层、传输层和应用层四个层次。
实际使用的网络模型是TCP/IP网络模型。
TCP/IP模型:
3.关于模型分层
在不同的层中,有不同的协议
二、网络通信三要素
1.IP地址
IP地址(Internet Protocol Address)是指互联网协议地址,又译为国际协议地址。通俗说就是在网络世界中,计算机的地址。网络中的计算机使用IP地址来进行唯一标识。
在Windows系统中,打开命令窗口(Windows+R)打开cmd,输入命令ipconfig(ip配置),按回车查看。包含了计算机的IP地址、子网掩码、默认网关等网络配置信息。如下:
在没有网络连接的情况下,只能自己电脑连接自己电脑。
对自己电脑的IP叫做本机回环地址,默认为127.0.0.1
2.端口号
端口号是计算机中的应用程序的整数数字标号,用来区分不同的应用程序。
0~1024为被系统使用或保留的端口号,0~65535为有效的端口号,也就是说开发的程序端口号,要选择1024~65535范围内的整数数字,但是不能与已有的端口冲突。
比如,MySQL(My Structured Query Language—>结构化查询语言)的端口号是3306,SQLServer的端口号是1433,Oracle的端口号是1521。以上三个都是数据库管理系统(DBMS->Database Manage System)
3.网络通信协议
传输层中有两个重要协议:
传输控制协议(TCP):Transmission Control Protocol
用户数据报协议(UDP):User Datagram Protocol
1.TCP
• 使用TCP协议前,须先建立TCP连接,形成传输数据通道
• 传输前,采用“三次握手”方式,是可靠的
更细化的“三次握手”:
• TCP协议进行通信的两个应用进程:客户端、服务端
• 在连接中可进行大数据量的传输
• 传输完毕,需释放已建立的连接,效率低
• 在断开时要进行“四次挥手”
更细化的四次挥手:
2.UDP
• 将数据、源、目的封装成数据包,不需要建立连接
• 每个数据报的大小限制在64K内
• 因无需连接,故是不可靠的
• 发送数据结束时无需释放资源,速度快
例如发射导弹(目标坐标),不知道是否发送成功,是不安全的,但效率高。
在一般的杀毒软件中可查看文件的连接协议。比如打开火绒的流量监控,点击查看所有连接,可查看到电脑上文件的连接协议。
三、TCP编程/UDP编程
TCP编程和UDP编程是基于TCP/UDP这两个重要网络通信协议下的编程
1.TCP编程
•利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准。
•通信的两端都要有Socket,是两台机器间通信的端点。
•网络通信其实就是Socket间的通信。
•Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
3.1.1对客户端(Socket)
Socket常用方法
客户端Socket工作过程包含四个基本步骤:
1.创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务 器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。
2.打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流, 使用getOutputStream()方法获得输出流,进行数据传输
3.按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
4.关闭 Socket:断开客户端到服务器的连接,释放线路
示例代码:
package com.ffyc;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
//创建客户端
Socket socket = new Socket("127.0.0.1",9999);
System.out.println("成功连接服务器");
//向服务器传输字节数据
OutputStream outputStream = socket.getOutputStream();
String s = "你好!";
//网络编程中传输的是字节数据(字节数组),所以我们需要把字符串转成字节数组
outputStream.write(s.getBytes());
//write(byte[] b) 方法的作用是将指定的字节数组 b 写入此输出流
} catch (IOException e) {
e.printStackTrace();
System.out.println("客户端连接异常");
}
}
}
3.1.2对服务器端(ServerSocket)
ServerSocket常用方法
服务器的工作过程
1.调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端 口上。用于监听客户端的请求。
2.调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信 套接字对象。
3.调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取 输出流和输入流,开始网络数据的发送和接收。
4.关闭ServerSocket和Socket对象:客户端访问结束,关闭通信套接字。
示例代码:
package com.ffyc;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
//创建并启动服务器
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器启动成功");
//监听有没有客户端连接到服务器
Socket socket = serverSocket.accept();
System.out.println("有客户成功连接到服务器");
//接收客户带发送的数据
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[100];
int size = inputStream.read(bytes);//read返回整数,即实际读取的字节数
String s = new String(bytes,0,size);//bytes是要读取的字节数组,0是从字节数组中开始读取的索引,size是要读取的字节数。
//不用toString转化是因为输入流中没有toString方法,也不会返回流中的数据。其中bytes数组充当缓冲区是必须的。
System.out.println("客户端"+s);
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器创建失败");
}
}
}
2.UDP编程
•类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序。
•UDP通过数据报套接字(Datagram Socket)发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
•DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址 和端口号以及接收端的IP地址和端口号。
•UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
UDP编程的流程:
1. DatagramSocket与DatagramPacket
2. 建立发送端,接收端
3. 建立数据报
4. 调用Socket的发送、接收方法
5. 关闭Socket
发送端和接收端是两个独立的运行程序
发送端示例代码:
DatagramSocket ds = new DatagramSocket();
byte[] by = “hello,baidu.com”.getBytes();
DatagramPacket dp = new DatagramPacket(by,0,by.length,
InetAddress.getByName(“127.0.0.1”),10000);
ds.send(dp);
ds.close();
接收端,要指定监听的端口:
DatagramSocket ds = new DatagramSocket(10000);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
ds.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str+"--"+dp.getAddress());
ds.close();