目录
一、多发多收
客户端:多次发送数据
服务器:接收多次数据,并打印
java
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10010);
Scanner scanner = new Scanner(System.in);
OutputStream os = socket.getOutputStream();
while (true) {
System.out.println("请输入内容:");
String str = scanner.nextLine();
os.write(str.getBytes());
if ("拜拜".equals(str)) {
break;
}
}
socket.close();
}
}
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10010);
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int len;
while ((len = br.read()) != -1) {
System.out.print((char) len);
}
socket.close();
serverSocket.close();
}
}
运行结果:
二、接收和反馈
客户端:发送一条数据,接收服务端反馈的消息并打印
服务器:接收数据并打印,再给客户端反馈消息
java
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10010);
// 写出数据
OutputStream os = socket.getOutputStream();
String str = "客户端发送消息:见到你很开心!";
os.write(str.getBytes());
// 写出结束标记
socket.shutdownOutput();
// 读取数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int len = 0;
while ((len = br.read()) != -1) {
System.out.print((char) len);
}
// 释放资源
socket.close();
}
}
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10010);
Socket socket = serverSocket.accept();
// 读取数据
// 细节:read方法会从连接通道中读取数据
// 但是,需要有一个结束标记,此处的循环才会停止,
// 否则,程序就会一直停在read方法这里,等待读取下面的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int len;
while ((len = br.read()) != -1) {
System.out.print((char) len);
}
// 写出数据
OutputStream os = socket.getOutputStream();
String str = "服务器发送消息:有多开心?";
os.write(str.getBytes());
// 释放资源
socket.close();
serverSocket.close();
}
}
运行结果:
三、上传文件
客户端:将本地文件上传到服务器,接收服务器的反馈。
服务器:接收客户端上传的文件,上传完毕之后给出反馈。
使用FileInputStream读取本地文件,使用FileOutputStream保存本地文件
java
public class Client {
public static void main(String[] args) throws IOException {
// 1.创建Socket对象,并连接服务器
Socket socket = new Socket("127.0.0.1", 10020);
// 2.读取本地文件中的数据,并写到服务器中
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("mysocketnet/clientdir/a.jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
// 向服务器写出结束标记
socket.shutdownOutput();
// 3.接收服务器的回写数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = br.readLine();
System.out.println(str);
// 4.释放资源
socket.close();
}
}
public class Server {
public static void main(String[] args) throws IOException {
// 1.创建对象并绑定端口
ServerSocket serverSocket = new ServerSocket(10020);
// 2.等待客户端来连接
Socket socket = serverSocket.accept();
// 3.读取客户端发送的数据,并将数据存入指定路径中
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet/serverdir/a.jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
// 4. 服务器向客户端回写数据
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("服务器向客户端发送消息:文件已接收!");
bw.newLine();
bw.flush();
// 5.释放资源
socket.close();
serverSocket.close();
}
}
运行结果:
四、解决上传文件名重复问题
Client代码无需修改
java
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10020);
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
// 方式一:使用毫秒值拼接
// BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + System.currentTimeMillis() + ".jpg"));
// 方式二:使用UUID拼接
String name = UUID.randomUUID().toString().replace("-", "");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + name + ".jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("文件上传成功!");
bw.newLine();
bw.flush();
socket.close();
serverSocket.close();
}
}
运行结果:
、
五、上传文件多线程版
让服务器不停止,能接收很多用户上传的图片,可以使用(循环+多线程)
Client代码无需修改
java
public class MyRunnable implements Runnable {
public Socket socket;
public MyRunnable(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-", "");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mysocketnet\\serverdir" + File.separator + name + ".jpg"));
int len;
byte[] bytes = new byte[1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("文件上传成功!");
bw.newLine();
bw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10020);
while (true) {
// 等待客户端来连接
Socket socket = serverSocket.accept();
// 一个用户对应服务端的一条线程
new Thread(new MyRunnable(socket)).start();
}
}
}
先开启Server,每开启一次Client,就会创建一个线程,文件也会上传
运行结果:
六、上传文件线程池版
频繁创建线程并销毁非常浪费系统资源,所以需要用线程池优化。
只需要修改Server即可:
java
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10020);
// 创建线程池对象
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
3, // 核心线程数量
16, // 线程池总大小
60, // 空闲时间
TimeUnit.SECONDS, // 空闲时间(单位)
new ArrayBlockingQueue<>(2), // 队列
Executors.defaultThreadFactory(), // 线程工厂,让线程池如何创建线程对象
new ThreadPoolExecutor.AbortPolicy() // 阻塞队列
);
while (true) {
Socket socket = serverSocket.accept();
// new Thread(new MyRunnable(socket)).start();
poolExecutor.submit(new MyRunnable(socket));
}
}
}
运行结果:
七、B/S(接收浏览器的消息并打印)
客户端:不需要写
服务器:接收数据并打印
java
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10010);
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int len;
char[] chars = new char[1024];
while ((len = br.read(chars)) != -1) {
System.out.println(new String(chars, 0, len));
br.readLine();
}
socket.close();
serverSocket.close();
}
}
浏览器输入:http://localhost:10010/
运行结果: