软件结构
C/S结构:
全称为Client(客户端)/Server(服务器端)结构,是指客户端和服务器结构
特点:
-
使用c/s结构需要开发两端,即客户端和服务器端
-
开发投入较大
-
安全性较低
-
但是服务器负载小,数据传输量小,效率高
B/S结构:
全称为Browser(浏览器)/Server(服务器端)结构,是指浏览器和服务器结构
特点:
-
使用b/s结构只需要开发一端,即服务器端
-
开发投入较小
-
安全性较高
-
但是服务器负载大,数据传输量较大,效率低
网络编程三要素:
协议:
udp:面向无连接的协议
安全性较低,效率高
tcp:面向有连接的协议
安全性高,效率低
ip地址:
即设备在网络中的位置地址(唯一)
ipv4
ipv6
端口号:
在电脑端进行应用程序的区分
UDP通信程序
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
UDP发送数据
DatagramSocket类
Java提供了DatagramSocket类作为基于UDP协议的Socket
DatagramSocker构造方法:
socket用于创建数据套接字,发送数据 packet用于创建数据包,将数据存入包内
DatagramSocker常用方法:
sent发送数据包 receive接收数据包 close关闭数据报套接字
DatagramSocket使用步骤
创建发送端的Socket对象(DatagramSocket)
创建数据,并把数据打包
调用DatagramSocket对象的方法发送数据
关闭发送端
代码实现:
客户端:
/**
* 客户端 发送数据
*/
public class client {
public static void main(String[] args) throws IOException {
//创建网络套接字
DatagramSocket socket = new DatagramSocket();
while (true) {
System.out.println("————————服务端连接成功————————");
//发送信息
Scanner sc = new Scanner(System.in);
System.out.println("请输入信息:");
String content = sc.nextLine();
//打包
byte[] bytes = content.getBytes();
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 9999);
socket.send(packet);
/*********************** 接收回信 ***************************/
//接收回复信息
byte[] replyBytes = new byte[1024];
//创建数据包
DatagramPacket replyPacket = new DatagramPacket(replyBytes, replyBytes.length);
//接收
socket.receive(replyPacket);
//展示
//获取内容
String replycontent = new String(replyBytes).trim();
//获取服务器端信息
InetAddress address = replyPacket.getAddress();
int port = replyPacket.getPort();
System.out.println(address.toString() + ": " + port + "输入的内容为:" +"\n"+ replycontent);
}
}
}
UDP接收数据
DatagramPacket构造方法:
DatagramPacket常用方法:
接收数据的步骤
创建接收端的Socket对象(DatagramSocket)
创建一个数据包,用于接收数据
调用DatagramSocket对象的方法接收数据
解析数据包,并把数据在控制台显示
关闭接收端
服务器端:
/**
* 服务器端,接收数据
*/
public class server {
public static void main(String[] args) throws IOException {
//创建数据报套接字
DatagramSocket socket = new DatagramSocket(9999);
while (true) {
System.out.println("————————客户端连接成功————————");
//创建数组,获取客户端内容
byte[] bytes = new byte[1024];
//接收客户端内容
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
socket.receive(packet);
String content = new String(bytes).trim();
//展示内容
//获取客户端ip地址
InetAddress address = packet.getAddress();
//获取客户端端口号
int port = packet.getPort();
System.out.println(address.toString() + ": " + port + "输入的内容是:" + "\n" + content);
/****************** 回信 ************************/
//创建扫描器
Scanner sc = new Scanner(System.in);
System.out.println("请输入回执信息:");
String replyContent = sc.nextLine();
//打包
byte[] replyBytes = replyContent.getBytes();
DatagramPacket replyPacket = new DatagramPacket(replyBytes, replyBytes.length,address,port);
//发送
socket.send(replyPacket);
}
}
}
TCP通信程序
tcp协议:面向连接,安全性高,理论上传输的数据是无上限的,效率较低(相对于UDP来说)
TCP发送数据
Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
三次握手:通过三次确认后再建立连接发送读取内容
四次挥手:通过四次状态确认之后,进行连接的断开操作
Socket类
Java为客户端提供了Socket类,用于创建客户端发送数据
Socket类构造方法:
Socket类方法:
getInputStream() 返回套接字的输入流
getOutputStream() 返回套接字的输出流
Tcp接收数据:
服务器端 输入流
步骤:
-
创建服务器套接字对象
-
获取客户端请求 accept();
-
创建字节输入流 通过字节数组 利用read(); 读取内容 再转换成字符串形式展示
-
关闭流和服务器端
代码示例:
public class TcpServer{
public static void main(String[] args) throws IOException {
//创建一个服务器套接字对象
ServerSocket server = new ServerSocket(6789);
//接收客户端请求
Socket socket = server.accept(); //accept() 返回的是一个socket对象
//读取内容
byte[] bytes = new byte[1024];
//创建一个字节输入流
InputStream input = socket.getInputStream();
int length = input.read(bytes);
if (length!=-1){ //读取到内容
String content = new String(bytes,0,length);
System.out.println(content);
}
//关闭流
input.close();
//关闭服务器
server.close();
}
}
升级版代码:
public class TcpClient2 {
public static void main(String[] args) throws IOException {
//创建客户端
Socket socket = new Socket("localhost", 6789);
//创建字节输入流
InputStream input = socket.getInputStream();
//创建字节输出流
OutputStream output = socket.getOutputStream();
//创建数组
byte[] bytes = new byte[1024];
//创建扫描器
Scanner sc = new Scanner(System.in);
//创建一个变量,记录内容长度
int length;
System.out.println("——————————服务器端连接成功——————————");
while (true){
/****** 发消息 *****/
System.out.println("客户端:请输入内容");
String content = sc.nextLine();
byte[] bytes1 = content.getBytes();
output.write(bytes1);
System.out.println("等待服务器端发送内容");
/****** 接收消息 ******/
length = input.read(bytes);
String serverMessage = new String(bytes, 0, length);
System.out.println("服务器消息:"+serverMessage);
if ("bye".equals(serverMessage)){
output.write("bye".getBytes());
break;
}
}
//关闭
input.close();
output.close();
socket.close();
}
}
Tcp发送数据:
客户端 输出流
步骤:
-
创建客户端套接字对象
-
创建字节输出流,输出内容
-
将想输出内容的字符串转为字节数组的形式 利用write(); 输出内容
-
关闭流和客户端
代码示例:
public class TcpClient {
public static void main(String[] args) throws IOException {
//创建一个客户端套接字对象
Socket client = new Socket("localhost",6789);
//创建字节输出流,输出内容
OutputStream output = client.getOutputStream();
//输出内容
Scanner sc = new Scanner(System.in);
System.out.println("请输入内容");
String content = sc.nextLine();
//将键盘输入的内容转为字节数组
byte[] bytes = content.getBytes();
//输出内容
output.write(bytes);
//关闭流
output.close();
//关闭客户端
client.close();
}
}
升级版代码:
public class TcpServer2 {
public static void main(String[] args) throws IOException {
//创建服务器端
ServerSocket server = new ServerSocket(6789);
//接收客户端请求
Socket socket = server.accept();
//创建字节输入流
InputStream input = socket.getInputStream();
//创建字节输出流
OutputStream output = socket.getOutputStream();
//创建数组
byte[] bytes = new byte[1024];
//创建扫描器
Scanner sc = new Scanner(System.in);
//创建变量
int length;
System.out.println("——————————客户端连接成功——————————");
while (true){
/*******接收信息 *****/
length = input.read(bytes);
String clientMessage = new String(bytes, 0, length);
System.out.println("客户端消息:"+clientMessage);
/****** 回执信息 ******/
if ("bye".equals(clientMessage)){
output.write(clientMessage.getBytes());
// output.write("bye".getBytes());
break;
}
System.out.println("服务器端:请输入内容");
String replyMessage = sc.nextLine();
byte[] bytes1 = replyMessage.getBytes();
//输出信息
output.write(bytes1);
System.out.println("等待客户端发送内容");
}
//关闭
input.close();
output.close();
server.close();
}
}