目录
练习一:简单的信息发送
-
发送端:数据来自键盘录入,直到输入的数据是bye,发送数据结束
-
接收端:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
发送端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;
public class UDP_Client2 {
/**
* 练习一:简单的信息发送
*
* 发送端:数据来自键盘录入,直到输入的数据是bye,发送数据结束
* 接收端:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//发送对象
DatagramSocket ds = new DatagramSocket();
Scanner scanner = new Scanner(System.in);
while(true){//字节数组
System.out.println("请输入要发送的内容:");
String msg = scanner.next();
byte[] data = msg.getBytes();
//目的地址
InetSocketAddress address = new InetSocketAddress("localhost", 1122);
//发送包裹
DatagramPacket dp = new DatagramPacket(data, data.length, address);
//发送
ds.send(dp);
System.out.println("已发送");
if(msg.equals("bye")){
System.out.println("over");
break;
}
}
//关闭
ds.close();
}
}
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDP_Server2 {
public static void main(String[] args) throws IOException {
//监听指定端口
DatagramSocket ds = new DatagramSocket(1122);
while(true){
System.out.println("等待接收");
//字节数组
byte[] data = new byte[1024];
//接受包裹
DatagramPacket dp = new DatagramPacket(data,data.length);
//阻塞式接收
ds.receive(dp);
String res = new String(data,0,dp.getLength());
System.out.println(res);
if(res.equals("bye")){
System.out.println("over");
break;
}
}
ds.close();
}
}
运行结果:
练习二:信息发送与接收
-
发送端:数据来自键盘录入,直到输入的数据是bye,发送数据结束,可以接收到服务端的响应
-
接收端:接收客户端的数据信息,并且及时做出响应
发送端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;
public class UDP_Client3 {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true){
System.out.println("请输入要发送的内容");
String msg = sc.next();
byte[] data = msg.getBytes();
InetSocketAddress address = new InetSocketAddress("localhost",1223);
DatagramPacket dp = new DatagramPacket(data,data.length,address);
ds.send(dp);
//接收
System.out.println("等待接收");
byte[] tmp = new byte[1024];
dp = new DatagramPacket(tmp,tmp.length);
ds.receive(dp);
String res = new String(tmp,0,dp.getLength());
System.out.println(res);
if(msg.equals("bye")){
System.out.println("over");
break;
}
}
ds.close();
}
}
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Scanner;
public class UDP_Server3 {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(1223);
Scanner sc = new Scanner(System.in);
while(true){
//接收
System.out.println("等待接收");
byte[] data = new byte[1024];
DatagramPacket dp = new DatagramPacket(data,data.length);
ds.receive(dp);
String res = new String(data,0,dp.getLength());
System.out.println(res);
//发送
System.out.println("请输入要发送的内容");
String msg = sc.next();
byte[] tmp = msg.getBytes();
dp = new DatagramPacket(tmp,tmp.length,dp.getAddress(),dp.getPort());
ds.send(dp);
if(res.equals("bye")){
System.out.println("over");
break;
}
}
ds.close();
}
}
运行结果:
练习三:数据来自键盘输入,接收到的数据输出到控制台
-
客户端: 数据来自于键盘录入,直到输入的数据是bye, 发送数据结束
-
服务器端:接收到的数据在控制台输出
客户端:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TCP_Client2 {
public static void main(String[] args) throws IOException {
//建立连接
Scanner scanner = new Scanner(System.in);
Socket socket = new Socket("localhost",1122);
PrintWriter pw;
//输入要发送的内容
while(true){
System.out.println("请输入要发送的内容:");
String msg = scanner.next();
pw = new PrintWriter(socket.getOutputStream());
pw.println(msg);
pw.flush();
if(msg.equals("bye")){
System.out.println("over");
break;
}
}
pw.close();
socket.close();
}
}
服务器端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_Server2 {
public static void main(String[] args) throws IOException {
//监听指定端口
ServerSocket serverSocket = new ServerSocket(1122);
//阻塞式接收
Socket socket = serverSocket.accept();
//将字节输入流转为带缓冲区的字符流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while((msg=br.readLine())!=null){
System.out.println(msg);
if(msg.equals("bye")){
System.out.println("over");
break;
}
}
br.close();
socket.close();
serverSocket.close();
}
}
运行结果:
练习四:简单的发送和接收数据
- 客户端: 发送数据,接收服务器反馈
- 服务器端: 接收数据,给出反馈
客户端:
import java.io.*;
import java.net.Socket;
/**
* @Author {那蓝桉}
* @Date: 2023/04/08/ 14:36
* @description 客户端: 发送数据,接收服务器反馈
*/
public class TCP_Client3 {
public static void main(String[] args) throws IOException {
// 创建客户端的Socket对象(Socket)
Socket socket = new Socket("localhost",1122);
// 获取输出流,写数据
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println("hello");
pw.flush();
socket.shutdownOutput();
//接收服务器反馈
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
//释放资源
br.close();
pw.close();
socket.close();
}
}
服务器端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Author {那蓝桉}
* @Date: 2023/04/08/ 14:36
* @description 服务器: 接收数据,给出反馈
*/
public class TCP_Server3 {
public static void main(String[] args) throws IOException {
// 创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(1122);
Socket socket = serverSocket.accept();
System.out.println("等待接收");
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while((line= br.readLine())!=null){
System.out.println(line);
}
//做出反馈
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println("数据已收到");
pw.flush();
//释放资源
pw.close();
br.close();
socket.close();
serverSocket.close();
}
}
运行结果:
练习五:上传文件
-
客户端:数据来自于文本文件或者图片
-
服务器端:接收到的数据写入文本文件或者图片
客户端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
public class TCP_Client4 {
public static void main(String[] args) throws IOException {
//建立连接
Socket socket = new Socket("localhost",1122);
//输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:/picture/cat.jpg"));
//输出流
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//读取数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
bos.close();
bis.close();
socket.close();
System.out.println("发送成功");
}
}
服务器端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_Server4 {
public static void main(String[] args) throws IOException {
//监听指定端口
ServerSocket serverSocket = new ServerSocket(1122);
//阻塞式接收
Socket socket = serverSocket.accept();
//输入流,获取客户端socket中的数据
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/cat.jpg"));
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
bos.close();
bis.close();
socket.close();
serverSocket.close();
System.out.println("上传成功");
}
}
运行结果:
练习六:上传文件,并得到服务器的反馈
- 客户端:数据来自于文本文件或者图片,接收服务器反馈
- 服务器:接收到的数据写入文本文件或者图片,给出反馈
出现问题: 程序一直等待
原因:读数据的方法是阻塞式的
解决方法:
1、自定义结束标记;
2、使用shutdownOutput() :禁用此套接字的输出流(推荐)
客户端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* @Author {那蓝桉}
* @Date: 2023/04/08/ 15:11
* @description 客户端:数据来自于文本文件或者图片,接收服务器反馈
*/
public class TCP_Client5 {
public static void main(String[] args) throws IOException {
//TCP需要建立连接
Socket socket = new Socket("localhost",1122);
//读取流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/picture/cat.jpg"));
//输出流
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//读取数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
bos.flush();
}
System.out.println("发送成功");
// bos.close();不能用
socket.shutdownOutput();//仅仅关闭输出流
BufferedInputStream bis2 = new BufferedInputStream(socket.getInputStream());
byte[] bytes = new byte[1024];
int len = bis2.read(bytes);
String str = new String(bytes,0,len);
System.out.println("收到服务器消息:"+str);
socket.close();
}
}
服务器端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Author {那蓝桉}
* @Date: 2023/04/08/ 15:11
* @description 服务器:接收到的数据写入文本文件或者图片,给出反馈
*/
public class TCP_Server5 {
public static void main(String[] args) throws IOException {
//监听指定端口
ServerSocket serverSocket = new ServerSocket(1122);
System.out.println("准备就绪");
//阻塞式接收
Socket socket = serverSocket.accept();
//获取客户端socket的数据
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/cat.jpg"));
//读取数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
bos.flush();
}
bos.close();
//服务器响应:向客户端发消息
BufferedOutputStream bos2 = new BufferedOutputStream(socket.getOutputStream());
bos2.write("上传完毕".getBytes());
bos2.close();
socket.close();
serverSocket.close();
System.out.println("通信结束");
}
}
运行结果:
练习七:服务器可以接收多个客户端上传的文件,线程封装
-
客户端: 数据来自文本文件或者图片,接收服务器反馈
-
服务器:接收到的数据写入文本文件或者图片,给出反馈,代码用线程封装,为每一个客户端开启一个线程
客户端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
public class TCP_Client6 {
public static void main(String[] args) throws IOException {
//TCP需要建立连接
Socket socket = new Socket("localhost",1122);
//读取流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/picture/cat.jpg"));
//输出流
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//读取数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
bos.flush();
}
System.out.println("发送成功");
// bos.close();不能用
socket.shutdownOutput();//仅仅关闭输出流
BufferedInputStream bis2 = new BufferedInputStream(socket.getInputStream());
byte[] bytes = new byte[1024];
int len = bis2.read(bytes);
String str = new String(bytes,0,len);
System.out.println("收到服务器消息:"+str);
socket.close();
}
}
服务器端:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ThreadServer extends Thread{
private Socket socket;
public ThreadServer(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {//获取客户端socket的数据
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
LocalDateTime localDateTime = LocalDateTime.now();
String fileName = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssms"));
System.out.println(fileName);
//输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/"+fileName+".jpg"));
//读取数据
int b;
while((b=bis.read())!=-1){
bos.write(b);
bos.flush();
}
bos.close();
//服务器响应:向客户端发消息
BufferedOutputStream bos2 = new BufferedOutputStream(socket.getOutputStream());
bos2.write("上传完毕".getBytes());
bos2.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCP_Server6 {
/**
* 服务端接收客户端发来的文件
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//监听指定端口
ServerSocket serverSocket = new ServerSocket(1122);
System.out.println("准备就绪");
while(true){
Socket socket =serverSocket.accept();
new ThreadServer(socket).start();
}
}
}
运行结果: