软件结构
C/S结构
Client/Server结构,客户端和服务器(下载的APP软件等)
B/S结构
Browser/Server结构,浏览器和服务器(谷歌,淘宝,京东等)
通信协议
TCP/IP协议
传输控制协议/因特网互联协议,是Internet最基本,最广泛的协议
定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。
四层模型:
链路层:用于定义物理传输通道,通常是对某些网络连接设备的驱动协议
网络层:tcp/ip协议的核心,主要用于传输的数据进行分组,将分组数据发送到目标计算机或者网络
传输层:主要使用网络程序进行通信,在进行网络通信时,可以采用tcp协议或者udp协议
应用层:主要负责应用程序的协议,http协议、ftp协议
UDP协议
用户数据报协议,面向无连接通信协议,数据的发送端与接收端不建立逻辑连接,消耗资源小,通信效率高,常用语音频视频等普通数据,面向无连接性,不能保证数据的完整性,数据被限制在64kb以内。
TCP协议
传输控制协议,面向连接的通信,数据传输之前,在发送端和接收端建立逻辑连接,再传输数据,在tcp连接中必须声明客户端和服务器端,有客户端向服务器端发出连接请求,每次连接的创建需要经过三次握手,比较安全。
三次握手
第一次握手,客户端向服务器端发送请,等待服务器确认
第二次握手,服务器端向客户端发送一个响应,通知服务端收到了连接请求
第三次握手,客户端再次向服务器端发送确认信息,确认连接。
完成三次握手建立连接后,客户端和服务器端就可以开始进行数据传输了。
网络编程三要素
协议(上面已介绍过);IP地址和端口号
IP地址
指互联网协议地址俗称ip
ip地址分类:
ipv4 32位的二进制数,通常被分为4个字节
ipv6 采用128位地址长度,没16个字节一组,分成8组16进制数
常用命令有:
常看本机ip地址:ipconfig/ipconfigall
检查网络是否连通:ping 空格 ip地址
特殊的IP地址:本机地址:127.0.0.1 localhost
端口号
用两个字节表示的整数,它的取值范围是0-65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
InetAddress类
该类用于封装一个ip地址,并提供了一系列与ip地址相关的方法
常用方法
public static InetAddress getLocalHost()返回本地主机。
public static InetAddress getByName(String host)根据ip和主机名获取InetAddress
public String getHostAddress()获取ip地址
public String getHostName()获取主机名
代码演示:
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// 获取本地主机
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost.getHostName());
System.out.println(localHost.getHostAddress());
// 根据主机名获取InetAddress
InetAddress inetAddress = InetAddress.getByName("PC201501241736");
System.out.println(inetAddress);
// 获取ip地址
System.out.println(inetAddress.getHostAddress());
// 获取主机名
System.out.println(inetAddress.getHostName());
}
}
UDP通信
UDP发送数据
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
DatagramSocket类
DatagramSocket类作为基于UDP协议的Socket
DatagramSocket构造方法
DatagramSocket()创建数据报套接字并将其绑定到本机地址上的任何可用端口
DatagramPacket(byte[] buf,int len,InetAddress add,int port)创建数据包,发送长度为len的数据包到指定主机的指定端口
DatagramSocket常用方法
void send(DatagramPacket p)发送数据报包
void close()关闭数据报套接字
void receive(DatagramPacket p)从此套接字接受数据报包
DatagramSocket使用步骤
创建发送端的Socket对象(DatagramSocket)
创建数据,并打包数据
调用DatagramSocket对象的方法发送数据
关闭发送端
代码演示:
public class SendDataDemo {
public static void main(String[] args) throws IOException {
/**
* 1. 创建发送端的Socket对象(DatagramSocket)
* 2. 创建数据,并打包数据
* 3. 调用DatagramSocket对象的方法发送数据
* 4. 关闭发送端
*/
DatagramSocket ds = new DatagramSocket();
byte[] bytes = "hello world".getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("172.16.16.94"),10001);
ds.send(dp);
ds.close();
}
}
UDP接收数据
DatagramPacket类构造
DatagramPacket(byte[] buf, int len)创建一个DatagramPacket用于接收长度为len的数据包
DatagramPacket类方法
byte[] getData()返回数据缓冲区
int getLength()返回要发送的数据的长度或接收的数据的长度
接收数据步骤
创建接收端的socket对象(DatagramSocket)
调用一个数据包,用于接受数据
调用DatagramSocket对象的方法就收数据
解析数据包,并把信息在控制台显示
关闭接收端
代码演示:
public class ReceiveDataDemo {
public static void main(String[] args) throws IOException {
/**
* 1. 创建接收端的socket对象(DatagramSocket)
* 2. 调用一个数据包,用于接受数据
* 3. 调用DatagramSocket对象的方法就收数据
* 4. 解析数据包,并把信息在控制台显示
* 5. 关闭接收端
*/
DatagramSocket ds = new DatagramSocket(12345);
while (true){
byte [] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
System.out.println("数据是:"+new String(dp.getData(),0,dp.getLength()));
}
}
}
TCP通信
TCP发送数据
Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
Socket类
Java为客户端提供了Socket类,用于创建客户端发送数据
Socket类构造
Socket(InetAddress address,int port)创建流套接字并将其连接到指定IP指定端口号
Socket(String host, int port)创建流套接字并将其连接到指定主机上的指定端口号
Socket类方法
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流
代码实现
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建Socket对象
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
Socket socket = new Socket("172.16.16.94", 10001);
//获取输出流,写数据
OutputStream os = socket.getOutputStream();
os.write("hello world".getBytes());
//释放资源
socket.close();
}
}
TCP接收数据
Java为服务器端提供了ServerSocket类,用于接收数据和处理数据
ServerSocket类构造
ServletSocket(int port)创建绑定到指定端口的服务器套接字
ServerSocket类方法
Socket accept()监听要连接到此的套接字并接受它
代码实现
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器的socket对象(ServerSocket)
//ServerSocket(int port)创建绑定到指定端口号的服务器套接字
ServerSocket serverSocket = new ServerSocket(10001);
//Socket accept()侦听要连接的套接字并接收它
Socket accept = serverSocket.accept();
//获取输入流,读数据,并将数据显示在控制台
InputStream is = accept.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
String data = new String(bytes, 0, len);
System.out.println("数据是:"+data);
//释放资源
accept.close();
serverSocket.close();
}
}
TCP通信案例
案例需求
客户端:发送数据
服务器:接收消息后并反馈
需求分析
客户端创建对象,使用输出流输出数据
服务端创建对象,使用输入流接收数据
服务端使用输出流给出反馈数据
客户端使用输入流接收返回数据
代码实现
服务端代码
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10001);
//侦听客户端连接,返回一个Socket对象
Socket socket = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
String data = new String(bytes, 0, len);
System.out.println("服务器接受的数据是:"+data);
//反馈
OutputStream os = socket.getOutputStream();
os.write("已受到数据".getBytes());
//释放资源
serverSocket.close();
}
}
客户端代码
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
Socket socket = new Socket("127.0.0.1", 10001);
//获取输出流,写数据
OutputStream os = socket.getOutputStream();
os.write("发送到服务器的数据".getBytes());
//接收服务端反馈的数据
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
String data = new String(bytes, 0, len);
System.out.println("客户端接受的数据:"+data);
//释放资源
socket.close();
}
}
聊天室案例
接收端代码
public class UDPReceive {
public static void main(String[] args) throws IOException {
//创建DatagramSocket并指定端口号
DatagramSocket ds = new DatagramSocket(10001);
byte[] bytes = new byte[1024];
while (true){
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
InetAddress address = dp.getAddress();
System.out.println("发送者:"+address.getHostAddress());
System.out.println(new String(data,0,length));
}
//释放资源
//ds.close();
}
}
发送端代码
public class UDPSend {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//从控制台输入聊天信息
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入聊天内容:");
String message = scanner.nextLine();
byte[] bytes = message.getBytes();
//发送数据
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 10001);
ds.send(dp);
}
//释放资源
//ds.close();
}
}