UDP
需求
完成在线咨询功能:
学生和咨询师在线一对一交流
分析
- 使用基于UDP协议的Socket网络编程实现
- 不需要使用IO流实现数据的传输
- 每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送的网络中,数据包在网络中寻找他的目的地
UDP基本概念
- DatagramSocket:用于发送和接受数据包的套接字
- DatagramPacket:数据包
步骤
接收端和发送端的端口不能冲突。
接收端:
- 使用DatagramSocket 指定端口,创建接收端
- 准备容器,封装成DatagramPacket包裹
- 阻塞式接受包裹receive(DatagramPacket p)
- 分析数据 : byte[] getData(),getLength()
- 释放资源
package Net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 接收端
* 使用DatagramSocket 指定端口,创建接收端
* 准备容器,封装成DatagramPacket包裹
阻塞式接受包裹receive(DatagramPacket p)
分析数据 : byte[] getData(),getLength()
释放资源
* @author 王星宇
* @date 2020年2月20日
*/
public class UdpServer {
public static void main(String[] args) throws Exception {
System.out.println("接受方启动中..");
// 使用DatagramSocket 指定端口,创建接收端
DatagramSocket ds = new DatagramSocket(9999);
// 准备容器,封装成DatagramPacket包裹
byte[] data = new byte[1024 * 60];
DatagramPacket dp = new DatagramPacket(data,0,data.length);
// 阻塞式接受包裹receive(DatagramPacket p)
ds.receive(dp);
// 分析数据 : byte[] getData(),getLength()
data = dp.getData();
int len = dp.getLength();
System.out.println(new String(data,0,len));
// 释放资源
ds.close();
}
}
发送端:
- 使用DatagramSocket 指定端口,创建发送端
- 准备数据,转化程字节数组
- 封装成DatagramPacket包裹,需要指定目的地
- 发送包裹send(DatagramPacket p)
- 释放资源
package Net;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* 发送端
* - 使用DatagramSocket 指定端口,创建发送端
- 准备数据,转化程字节数组
- 封装成DatagramPacket包裹,需要指定目的地
- 发送包裹send(DatagramPacket p)
- 释放资源
* @author 王星宇
* @date 2020年2月20日
*/
public class UdpClient {
public static void main(String[] args) throws Exception {
System.out.println("发送方启动中。。。");
// - 使用DatagramScoket 指定端口,创建发送端
DatagramSocket ds = new DatagramSocket(8888);
// - 准备数据,转化程字节数组
String msg = "天才王二狗";
byte[] data = msg.getBytes();
// - 封装成DatagramPacket包裹,需要指定目的地
DatagramPacket dp = new DatagramPacket(data,0,data.length,
new InetSocketAddress("localhost",9999));
// - 发送包裹send(DatagramPacket p)
System.out.println("发送中");
ds.send(dp);
// - 释放资源
ds.close();
System.out.println("发送完成");
}
}
上传文件
要发送什么样的数据,就用字节流对应数据类型的IO流。下面是自己写的发送文件的IO工具类,实现了将文件转化为字节数组,用来发送;将字节数组转化为文件,用来接收。
注:文件不能发送太大,一般最大60KB,否则会报错。
public class IOUtils {
public static byte[] fileToByteArray(String path) {
File src = new File(path);
byte[] flush = null;
InputStream is = null;
try {
is = new FileInputStream(src);
flush = new byte[1024 * 60];
is.read(flush);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return flush;
}
public static File byteArrayToFile(String path,byte[] flush) {
File file = new File(path);
OutputStream os = null;
try {
os = new FileOutputStream(file,false);
os.write(flush,0,flush.length);
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(os != null)
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
}
TCP
需求
完成网络登录功能:
用户输入用户名,密码,服务器给出登录成功或失败的提示
分析
- 使用基于TCP协议的Socket网络编程实现
- TCP基于请求-响应模式
- 在网络通讯中,第一次发送通讯的程序被称作客户端(Client)程序
- 第一次通讯中等待连接的程序被称作服务器端(Server)程序(监听客户端的连接)
- 利用IO流实现数据的传输
步骤
- 先创建服务器ServerSocket,在指定端口监听并处理请求
- 再创建客户端Socket,向服务端发送请求
服务器:
- 1,使用ServerSocket创建服务器,指定端口
- 2,阻塞式等待连接 accept()
- 3,操作:IO流
- 4,释放资源
package Net;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 1,使用ServerSocket创建服务器,指定端口
* 2,阻塞式等待连接 accept()
* 3,操作:IO流
* 4,释放资源
* @author 王星宇
* @date 2020年2月20日
*/
public class TCPServe {
public static void main(String[] args) throws Exception {
System.out.println("---------Server-----------");
// * 1,使用ServeSocket创建服务器,指定端口
ServerSocket server = new ServerSocket(9999);
// * 2,阻塞式等待连接 accept()
Socket client = server.accept();
System.out.println("一个客户端建立了连接");
// * 3,操作:IO流
DataInputStream dis = new DataInputStream(client.getInputStream());
String msg = dis.readUTF();
System.out.println("来自客户端的消息:" + msg);
// * 4,释放资源\
dis.close();
client.close();
server.close();
}
}
客户端:
- 1,使用Socket创建客户端 指定服务器的地址和端口
- 2,操作:IO流
- 3,释放资源
package Net;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 1,使用Socket创建客户端 指定服务器的地址和端口
* 2,操作:IO流
* 3,释放资源
* @author 王星宇
* @date 2020年2月20日
*/
public class TCPClient {
public static void main(String[] args) throws Exception {
System.out.println("---------Client-----------");
// * 1,使用Socket创建客户端 指定服务器的地址和端口
Socket client = new Socket("localhost",9999);
// * 2,操作:IO流
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
String msg = "hello";
dos.writeUTF(msg);
dos.flush();
// * 3,释放资源
dos.close();
client.close();
}
}
网络登录 /文件上传
在登录的时候,服务器会向客户端返回登录的结果,也就是服务器向客户端发送信息,操作和客户端向服务器发送信息一样。
在服务器添加下列代码,分析数据,返回结果
String user = "";
String password = "";
//分析数据
String[] info = msg.split("&");
for(String users : info) {
String userInfo[] = users.split("=");
System.out.println(users);
if(userInfo[0].equals("user")) {
user = userInfo[1];
}else {
password = userInfo[1];
}
}
//返回登录信息
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
if(user.equals("聪明的王二狗") && password.equals("123456")) {
dos.writeUTF("登录成功!");
System.out.println("用户登录成功");
}else {
dos.writeUTF("用户名或密码错误");
System.out.println("用户登录失败");
}
dos.flush();
在客户端添加下列代码,查询登录状态
//查询登录状态
DataInputStream dis = new DataInputStream(client.getInputStream());
String msg = dis.readUTF();
System.out.println(msg);
文件上传,用TCP没有文件大小的限制
服务器
//文件操作
InputStream is = new BufferedInputStream(client.getInputStream());
OutputStream os = new BufferedOutputStream(new FileOutputStream("TCP副本.txt"));
byte[] data = new byte[1024];
int len = -1;
while((len = is.read(data)) != -1) {
os.write(data,0,len);
}
os.flush();
os.close();
is.close();
System.out.println("文件上传成功");
客户端
//文件操作
InputStream is = new BufferedInputStream(new FileInputStream("我是天才"));
OutputStream os = new BufferedOutputStream(client.getOutputStream());
byte[] data = new byte[1024];
int len = -1;
while((len = is.read(data)) != -1) {
os.write(data,0,len);
}
os.flush();
os.close();
is.close();