目录
一、多发多收
二、接收和反馈
三、上传文件
四、解决上传文件名重复问题
五、上传文件多线程版
六、上传文件线程池版
七、B/S(接收浏览器的消息并打印)
一、多发多收
客户端:多次发送数据
服务器:接收多次数据,并打印
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();}
}
运行结果:
二、接收和反馈
客户端:发送一条数据,接收服务端反馈的消息并打印
服务器:接收数据并打印,再给客户端反馈消息
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保存本地文件
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代码无需修改
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代码无需修改
public class MyRunnable implements Runnable {public Socket socket;public MyRunnable(Socket socket) {this.socket = socket;}@Overridepublic 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即可:
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(接收浏览器的消息并打印)
客户端:不需要写
服务器:接收数据并打印
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/
运行结果: