当前位置: 首页 > news >正文

第16章_网络编程拓展练习(TCP编程,UDP编程)

文章目录

  • 第16章_网络编程拓展练习
    • TCP编程
      • 1、学生与老师交互
      • 2、查询单词
      • 3、拓展:查询单词
      • 4、图片上传
      • 5、拓展:图片上传
      • 6、多个客户端上传文件
      • 7、群聊
    • UDP编程
      • 8、群发消息

第16章_网络编程拓展练习


TCP编程

1、学生与老师交互

案例:客户端模拟学生咨询,服务器端模拟咨询老师,进行交互。

客户端收到信息:

​ 欢迎咨询尚硅谷!

​ 这个月的所有期班都已经满了,只能报下一个月的了!

在这里插入图片描述

服务器端收到信息:

​ 你好,我想报名这个月的JavaEE就业班!

​ 好的,赶紧给我占个座!

在这里插入图片描述

提示:

(1)如果是一个客户端与服务器端交互,怎么实现

(2)如果是多个客户端与服务器交互,怎么实现

package com.atguigu.exercise1;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;public class Exercise1Client {public static void main(String[] args) {Socket socket = null; // 创建Socket指定ip地址和端口号PrintStream ps = null;try {socket = new Socket("127.0.0.1", 8888);// 获取输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println(br.readLine());// 获取输出流ps = new PrintStream(socket.getOutputStream());ps.println("你好,我想报名这个月的JavaEE就业班!");System.out.println(br.readLine());ps.println("好的,赶紧给我占个座!");} catch (IOException e) {e.printStackTrace();} finally {if (ps != null)ps.close();if (socket != null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

(1)服务端接收1个客户端访问

package com.atguigu.exercise1;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;public class Exercise1Server {public static void main(String[] args) {ServerSocket server = null;Socket socket = null;try {server = new ServerSocket(8888);socket = server.accept();// 获取输出流PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("欢迎咨询尚硅谷!");// 获取输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println(socket.getInetAddress().getHostAddress() + "留言:" + LocalDateTime.now());System.out.println(br.readLine() + "\n");ps.println("这个月的所有期班都已经满了,只能报下一个月的了!");System.out.println(socket.getInetAddress().getHostAddress() + "留言:" + LocalDateTime.now());System.out.println(br.readLine());} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}
}

(2)服务端接收多个客户端访问

package com.atguigu.exercise1;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;public class Exercise1 {public static void main(String[] args) {ServerSocket server = null;try {server = new ServerSocket(8888);boolean flag = true;while (flag) {Socket socket = server.accept();new Thread() {public void run() {try {// 获取输出流PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("欢迎咨询尚硅谷");// 获取输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println(socket.getInetAddress().getHostAddress() + "留言:" + LocalDateTime.now());System.out.println(br.readLine() + "\n");ps.println("这个月的所有期班都已经满了,只能报下一个月的了!");System.out.println(socket.getInetAddress().getHostAddress() + "留言:" + LocalDateTime.now());System.out.println(br.readLine());socket.close();} catch (IOException e) {e.printStackTrace();}}}.start();}} catch (IOException e) {e.printStackTrace();} finally {try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}
}

2、查询单词

案例:模拟客户端输入要查询的中文,服务器返回对应的英文单词

效果如下:

在这里插入图片描述

在这里插入图片描述

开发提示:

(1)服务器端有一个map,key是中文词语,value是对应的单词

(2)服务器接收到客户端的词语后,从map中get,如果可以找到,就返回单词,如果找不到,就返回“没有找到”

package com.atguigu.exercise2;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;public class Exercise2Server {public static void main(String[] args) {ServerSocket server = null;Socket socket = null;try {HashMap<String, String> dictionary = new HashMap<String, String>();dictionary.put("星期一", "Monday");dictionary.put("星期二", "Tuesday");dictionary.put("星期三", "Wednesday");dictionary.put("星期四", "Thursday");dictionary.put("星期五", "Friday");dictionary.put("星期六", "Saturday");dictionary.put("星期七", "Sunday");//...server = new ServerSocket(8888);socket = server.accept();// 获取输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 获取输出流PrintStream ps = new PrintStream(socket.getOutputStream());//接收客户端的中文String key = br.readLine();//查询对应的英文单词,并返回结果String words = dictionary.get(key);if (words != null) {ps.println(words);} else {ps.println("o(╥﹏╥)o没有找到对应的单词!");}} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}
}
package com.atguigu.exercise2;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;public class Exercise2Client {public static void main(String[] args) {Socket socket = null;Scanner input = null;try {// 创建Socket指定ip地址和端口号socket = new Socket("127.0.0.1", 8888);input = new Scanner(System.in);System.out.print("请输入要查询的词语:");String content = input.next();// 获取输出流PrintStream ps = new PrintStream(socket.getOutputStream());ps.println(content);// 获取输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println("查询结果:" + br.readLine());} catch (IOException e) {e.printStackTrace();} finally {try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}if (input != null)input.close();}}
}

3、拓展:查询单词

修改前一个题目,改为并发版。

服务器端:

package com.atguigu.exercise3;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;public class Exercise3Server {private static HashMap<String, String> dictionary = new HashMap<String, String>();static {dictionary.put("星期一", "Monday");dictionary.put("星期二", "Tuesday");dictionary.put("星期三", "Wednesday");dictionary.put("星期四", "Thursday");dictionary.put("星期五", "Friday");dictionary.put("星期六", "Saturday");dictionary.put("星期七", "Sunday");}public static void main(String[] args) {ServerSocket server = null;try {server = new ServerSocket(8888);while (true) {Socket socket = server.accept();new QueryThread(socket).start();}} catch (IOException e) {e.printStackTrace();} finally {try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}private static class QueryThread extends Thread {Socket socket;public QueryThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {BufferedReader br = null;PrintStream ps = null;try {// 获取输入流br = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 获取输出流ps = new PrintStream(socket.getOutputStream());//接收客户端的中文String key = br.readLine();//查询对应的英文单词,并返回结果String words = dictionary.get(key);if (words != null) {ps.println(words);} else {ps.println("o(╥﹏╥)o没有找到对应的单词!");}} catch (IOException e) {e.printStackTrace();;} finally {try {if (br != null)br.close();} catch (IOException e) {e.printStackTrace();}if (ps != null)ps.close();try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

客户端:

package com.atguigu.exercise3;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;public class Exercise3Client {public static void main(String[] args) {Socket socket = null;Scanner input = null;PrintStream ps = null;BufferedReader br = null;try {// 创建Socket指定ip地址和端口号socket = new Socket("127.0.0.1", 8888);input = new Scanner(System.in);System.out.print("请输入要查询的词语:");String content = input.next();// 获取输出流ps = new PrintStream(socket.getOutputStream());ps.println(content);// 获取输入流br = new BufferedReader(new InputStreamReader(socket.getInputStream()));System.out.println("查询结果:" + br.readLine());} catch (IOException e) {e.printStackTrace();} finally {if (ps != null)ps.close();try {if (br != null)br.close();} catch (IOException e) {e.printStackTrace();}try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}if (input != null)input.close();}}
}

4、图片上传

案例:客户端给服务器端上传照片

要求:

(1)客户端上传的照片,需要是jpg格式的,并且大小在2M(含)以内的,否则不能上传

(2)要求上传成功后,服务器要返回上传成功,如果上传失败,服务器返回上传失败

(3)客户端上传到服务器端的照片,存储在项目名下"photo"的文件夹中,并且以“照片原文件名+时间戳.jpg”命名

效果如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.atguigu.exercise4;import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;public class Exercise4Server{public static void main(String[] args) {ServerSocket server = null;Socket socket = null;DataInputStream dis = null;PrintStream ps = null;FileOutputStream fos = null;try {//开启服务器server = new ServerSocket(8888);//接收一个客户端的连接socket = server.accept();//获取输入流dis = new DataInputStream(socket.getInputStream());//获取输出流ps = new PrintStream(socket.getOutputStream());//(1)先读取文件名String filename = dis.readUTF();//(2)生成唯一的文件名String destfile = "photo" + "/" + filename + System.currentTimeMillis() + ".jpg";//(3)读取文件内容,并写入目标文件fos = new FileOutputStream(destfile);try {byte[] data = new byte[1024];int len;while ((len = dis.read(data)) != -1) {fos.write(data, 0, len);}//返回结果给客户端ps.println("接收成功!");} catch (Exception e) {//返回结果给客户端ps.println("接收失败!");}} catch (IOException e) {e.printStackTrace();} finally {try {if (fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}ps.close();try {if (dis != null)dis.close();} catch (IOException e) {e.printStackTrace();}try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}
}
package com.atguigu.exercise4;import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Scanner;public class Exercise4Client {public static void main(String[] args)throws IOException {//连接服务器Socket socket= new Socket("127.0.0.1",8888);//选择要上传的文件Scanner input = new Scanner(System.in);System.out.println("请选择要上传的文件:");//例如:D:\尚硅谷_0325班_柴林燕_JavaSE\笔记\第14章 IO流.docxString fileStr  = input.nextLine();File file = new File(fileStr);if(!fileStr.endsWith(".jpg")){System.out.println("照片必须是.jpg格式");input.close();socket.close();return;}if(file.length()>1024*1024*2){System.out.println("照片必须在2M(含)以内");input.close();socket.close();return;}DataOutputStream dos = null;//从file读取内容,给服务器发送FileInputStream fis = null;try {//获取输出流dos = new DataOutputStream(socket.getOutputStream());//先发送文件名dos.writeUTF(file.getName().substring(0, file.getName().lastIndexOf(".")));//发送文件内容fis = new FileInputStream(file);byte[] data = new byte[1024];int len;while((len = fis.read(data)) !=-1){dos.write(data, 0, len);}socket.shutdownOutput();//告诉服务器,我发送完毕} catch (Exception e) {System.out.println("上传失败");}finally{fis.close();dos.close();}//接收结果BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String result = br.readLine();System.out.println(result);br.close();socket.close();input.close();}}

5、拓展:图片上传

相较于上题,修改为并发版。

服务器端:

package com.atguigu.exercise5;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;public class Exercise5Server {public static void main(String[] args) {ServerSocket server = null;try {//开启服务器server = new ServerSocket(8888);while (true) {//接收一个客户端的连接Socket socket = server.accept();new UploadPhotoThread(socket).start();}} catch (IOException e) {e.printStackTrace();} finally {try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}private static class UploadPhotoThread extends Thread {Socket socket;public UploadPhotoThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try (//获取输入流ObjectInputStream dis = new ObjectInputStream(socket.getInputStream());//获取输出流PrintStream ps = new PrintStream(socket.getOutputStream());){//(1)先读取文件名String filename = dis.readUTF();//(2)生成唯一的文件名String destfile = "photo" + "/" + filename + System.currentTimeMillis() + ".jpg";//(3)读取文件内容,并写入目标文件FileOutputStream fos = null;try {fos = new FileOutputStream(destfile);byte[] data = new byte[1024];int len;while ((len = dis.read(data)) != -1) {fos.write(data, 0, len);}//返回结果给客户端ps.println("接收成功!");} catch (Exception e) {//返回结果给客户端ps.println("接收失败!");} finally {fos.close();}} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

客户端:

package com.atguigu.exercise5;import java.io.*;
import java.net.Socket;
import java.util.Scanner;public class Exercise5Client {public static void main(String[] args) throws IOException {//连接服务器Socket socket = new Socket("127.0.0.1", 8888);//选择要上传的文件Scanner input = new Scanner(System.in);System.out.println("请选择要上传的文件:");//例如:D:\尚硅谷_0325班_柴林燕_JavaSE\笔记\第14章 IO流.docxString fileStr = input.nextLine();File file = new File(fileStr);if (!fileStr.endsWith(".jpg")) {System.out.println("照片必须是.jpg格式");input.close();socket.close();return;}if (file.length() > 1024 * 1024 * 2) {System.out.println("照片必须在2M(含)以内");input.close();socket.close();return;}//获取输出流ObjectOutputStream dos = new ObjectOutputStream(socket.getOutputStream());//先发送文件名dos.writeUTF(file.getName().substring(0, file.getName().lastIndexOf(".")));//从file读取内容,给服务器发送FileInputStream fis = new FileInputStream(file);//发送文件内容byte[] data = new byte[1024];int len;while ((len = fis.read(data)) != -1) {dos.write(data, 0, len);}socket.shutdownOutput();//告诉服务器,我发送完毕//接收结果BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String result = br.readLine();System.out.println(result);fis.close();dos.close();br.close();socket.close();input.close();}}

6、多个客户端上传文件

需求:每一个客户端启动后都可以给服务器上传一个文件;服务器接收到文件后保存到一个upload目录中,可以同时接收多个客户端的文件上传。

思考分析:

(1)服务器端要“同时”处理多个客户端的请求,那么必须使用多线程,每一个客户端的通信需要单独的线程来处理。

(2)服务器保存上传文件的目录只有一个upload,而每个客户端给服务器发送的文件可能重名,所以需要保证文件名的唯一。我们可以使用“时间戳”作为文件名,而后缀名不变

(3)客户端需要给服务器上传文件名(含后缀名)以及文件内容。而文件名是字符串,文件内容不一定是纯文本的,因此选择ObjectOutputStream 和 ObjectInputStream。

服务器示例代码:

package com.atguigu.exercise6;import java.net.ServerSocket;
import java.net.Socket;public class Exercise6Server {public static void main(String[] args) {ServerSocket server = null;try {//服务器在8888端口号监听数据server = new ServerSocket(8888);while (true) {//(2)等待连接//这句代码执行一次,意味着一个客户端连接Socket accept = server.accept();FileUploadThread ft = new FileUploadThread(accept);ft.start();}} catch (IOException e) {e.printStackTrace();} finally {try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}
}
package com.atguigu.exercise6;import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;public class FileUploadThread extends Thread {private Socket socket;private String dir = "upload/";//可以把它放到配置文件中public FileUploadThread(Socket socket) {this.socket = socket;}public void run() {FileOutputStream fos = null;ObjectInputStream dis = null;PrintStream ps = null;try {InputStream is = socket.getInputStream();dis = new ObjectInputStream(is);OutputStream out = socket.getOutputStream();ps = new PrintStream(out);//读取文件名(含后缀名)String filename = dis.readUTF();int lastIndexOfDot = filename.lastIndexOf(".");//截取后缀名String ext = filename.substring(lastIndexOfDot);//生成时间戳SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmssSSS");//拼接新文件名 = 旧文件名 + 时间戳 + 后缀名String newFilename = filename.substring(0, lastIndexOfDot) + sf.format(new Date()) + ext;//拼接文件路径String pathname = dir + File.separator + newFilename;//用新文件路径构建文件输出流fos = new FileOutputStream(pathname);//接收文件内容byte[] data = new byte[1024];long sum = 0;int len;while ((len = dis.read(data)) != -1) {fos.write(data, 0, len);fos.flush();sum += len;}System.out.println("sum = " + sum);//返回结果ps.println(filename + "已上传完毕");} catch (Exception e) {e.printStackTrace();} finally {try {fos.close();} catch (IOException e) {e.printStackTrace();}try {if (dis != null)dis.close();} catch (IOException e) {e.printStackTrace();}if (ps != null)ps.close();try {socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

客户端示例代码:

package com.atguigu.exercise6;import java.io.*;
import java.net.Socket;
import java.util.Scanner;public class Exercise6Client {public static void main(String[] args) {// (1)连接服务器Socket socket = null;FileInputStream fis = null;ObjectOutputStream dos = null;OutputStream out = null;Scanner input = null;BufferedReader br = null;try {socket = new Socket("127.0.0.1", 8888);input = new Scanner(System.in);out = socket.getOutputStream();// 用它的目的是为了既可以单独传一个字符串,又可以写字节内容dos = new ObjectOutputStream(out);InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is);// 把字节流转成字符流br = new BufferedReader(isr);// (2)从键盘输入文件的路径和名称System.out.print("请选择要上传的文件:");String path = input.nextLine();File file = new File(path);// 先发送文件名(含后缀名)dos.writeUTF(file.getName());// 单独发一个字符串// 还需要一个IO流,从文件读取内容,给服务器发过去fis = new FileInputStream(file);// (3)把文件内容给服务器传过去,类似与复制文件byte[] data = new byte[1024];int len;long sum = 0;while ((len = fis.read(data)) != -1) {dos.write(data, 0, len);sum += len;dos.flush();}System.out.println("sum = " + sum);socket.shutdownOutput();//数据发送完毕,不再发送,但是还要接收,所以是半关闭// (4)接收服务器返回的结果String result = br.readLine();System.out.println(result);} catch (Exception e) {e.printStackTrace();} finally {// (5)关闭try {if (fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}try {if (dos != null)dos.close();} catch (IOException e) {e.printStackTrace();}try {if (out != null)out.close();} catch (IOException e) {e.printStackTrace();}if (input != null)input.close();try {if (br != null)br.close();} catch (IOException e) {e.printStackTrace();}try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

7、群聊

需求:客户端与服务器连接成功后,就可以看到其他客户端的发送的聊天信息,当前客户端也可以发送自己的聊天信息。

思考分析:

(1)服务器

要同时接收多个客户端的连接,因此需要多线程

服务器这边充当转发角色,即在服务器这边的某个客户端的Socket接收到自己客户端发送的消息后,要通过服务器端这边其他客户端的Socket将信息转发出去

(2)客户端

同时能够接收和发送消息,因此也要两个线程,一个接收,一个发送

在这里插入图片描述

服务器端示例代码:

package com.atguigu.exercise7;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;public class Exercise7Server {private static ArrayList<Socket> online = new ArrayList<Socket>();public static void main(String[] args) {ServerSocket server = null;try {//1、开启服务器server = new ServerSocket(9999);while (true) {//2、接收客户端的连接Socket socket = server.accept();//把这个客户端加入到online中online.add(socket);//每一个客户端独立的线程MessageHandler mh = new MessageHandler(socket);mh.start();}} catch (IOException e) {e.printStackTrace();} finally {try {if (server != null)server.close();} catch (IOException e) {e.printStackTrace();}}}private static class MessageHandler extends Thread {private Socket socket;private String ip;public MessageHandler(Socket socket) {super();this.socket = socket;this.ip = socket.getInetAddress().getHostAddress();}public void run() {BufferedReader br = null;PrintStream ps = null;try {//接收当前的客户端发送的消息InputStream in = socket.getInputStream();InputStreamReader isr = new InputStreamReader(in);br = new BufferedReader(isr);//这个客户端的一连接成功,线程一启动,就可以告诉其他人我上线了sendToOthers(ip + "上线了");while (true) {String content = br.readLine();if (content == null) {break;}//收到一句,转发一句sendToOthers(ip + "说:" + content);if ("bye".equals(content)) {//给自己发一句byeOutputStream out = socket.getOutputStream();ps = new PrintStream(out);ps.println("bye");break;}}sendToOthers(ip + "下线了");} catch (IOException e) {sendToOthers(ip + "掉线了");} finally {try {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}try {if (br != null)br.close();} catch (IOException e) {e.printStackTrace();}if (ps != null)ps.close();}}//因为转发的代码也很长,独立为一个方法public void sendToOthers(String str) {//遍历所有online的客户端Iterator<Socket> iterator = online.iterator();while (iterator.hasNext()) {Socket on = iterator.next();if (!on.equals(socket)) {//只给其他客户端转发try {OutputStream out = on.getOutputStream();PrintStream ps = new PrintStream(out);//不能用try(){}catch,因为这里不能关闭流和其他socketps.println(str);} catch (IOException e) {//说明on这个客户端要么下线了,要么掉线了iterator.remove();}}}}}
}

客户端示例代码:

package com.atguigu.exercise7;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;public class Exercise7Client {public static void main(String[] args) {Socket socket = null;try {// 1、连接服务器socket = new Socket("127.0.0.1", 9999);// 2、开启两个线程,一个收消息,一个发消息SendThread st = new SendThread(socket);ReceiveThread rt = new ReceiveThread(socket);st.start();rt.start();// 等发送线程停下来再往下走st.join();rt.interrupt();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();} finally {//关闭sockettry {if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}}}static class SendThread extends Thread {private Socket socket;public SendThread(Socket socket) {super();this.socket = socket;}public void run() {Scanner input = null;PrintStream ps = null;try {// 键盘输入input = new Scanner(System.in);OutputStream out = socket.getOutputStream();ps = new PrintStream(out);while (true) {// 从键盘输入System.out.print("请输入要发送的消息:");String content = input.nextLine();// 给服务器发送ps.println(content);// 如果bye,就结束发送if ("bye".equals(content)) {break;}}} catch (IOException e) {e.printStackTrace();} finally {if (input != null)input.close();if (ps != null)ps.close();}}}static class ReceiveThread extends Thread {private Socket socket;public ReceiveThread(Socket socket) {super();this.socket = socket;}public void run() {BufferedReader br = null;try {InputStream in = socket.getInputStream();InputStreamReader isr = new InputStreamReader(in);br = new BufferedReader(isr);while (true) {String line = br.readLine();if ("bye".equals(line)) {break;}System.out.println(line);}} catch (SocketException e) {System.out.println("退出");} catch (IOException e) {e.printStackTrace();} finally {if (br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}}}
}

UDP编程

8、群发消息

案例:模拟给全部同学群发“欢迎来到尚硅谷”

开发提示:使用UDP群发

package com.atguigu.exercise8;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class Exercise8Send {public static void main(String[] args) {DatagramSocket ds = null;try {//(1)先建立一个DatagramSocketds = new DatagramSocket();//(2)准备发送的数据String str = "欢迎来到尚硅谷";byte[] data = str.getBytes();for (int i = 0; i <= 255; i++) {//(3)把数据包装成一个数据报//DatagramPacket(byte[] buf, int length, InetAddress address, int port)/** 第一个参数:要发送的数据的字节数组* 第二个参数:数组的长度* 第三个参数:接收方的IP地址* 第三个参数:接收方的端口号** 好比发快递,需要填写接收方的IP和端口号*/InetAddress ip = InetAddress.getByName("192.168.11." + i);int port = 8888;DatagramPacket dp = new DatagramPacket(data, data.length, ip, port);//(4)发送数据报// 通过socket发送ds.send(dp);}} catch (IOException e) {e.printStackTrace();} finally {//(5)断开if (ds != null)ds.close();}}
}
package com.atguigu.exercise8;import java.net.DatagramPacket;
import java.net.DatagramSocket;public class Exercise8Receiver {public static void main(String[] args) {DatagramSocket ds = null;try {//1、准备一个socket,用来接收消息//接收方,先确定端口号,监听数据的端口号//好比,要收到快递,需要先确定自己的地址和手机号,然后对方才能给你发ds = new DatagramSocket(8888);//2、准备一个数据报,来接收数据//DatagramPacket(byte[] buf, int length)byte[] data = new byte[1024 * 64];//64KDatagramPacket dp = new DatagramPacket(data, data.length);//3、接收数据ds.receive(dp);//4、拆包裹byte[] result = dp.getData();int len = dp.getLength();//实际接收的数据的长度System.out.println(new String(result, 0, len));} catch (IOException e) {e.printStackTrace();} finally {//5、关闭if (ds != null)ds.close();}}
}

相关文章:

第16章_网络编程拓展练习(TCP编程,UDP编程)

文章目录 第16章_网络编程拓展练习TCP编程1、学生与老师交互2、查询单词3、拓展&#xff1a;查询单词4、图片上传5、拓展&#xff1a;图片上传6、多个客户端上传文件7、群聊 UDP编程8、群发消息 第16章_网络编程拓展练习 TCP编程 1、学生与老师交互 案例&#xff1a;客户端模…...

深入Docker5:安装nginx部署完整项目

目录 准备 为什么要使用nginx mysql容器构建 1.删除容器 2.创建文件夹 3.上传配置文件 4.命令构建mysql容器 5.进入mysql容器&#xff0c;授予root所有权限 6.在mysql中用命令运行sql文件 7.创建指定数据库shop 8.执行指定的sql文件 nginx安装与部署 1.拉取镜像 2…...

HBASE学习四:常用命令汇总梳理(包括数据库、zk、hdfs相关操作与配置)

1、服务状态 1、后台查询 hbase shell #进入hbase的shell页面,配置环境变量可直接执行。status #查看当前服务状态status detailed #查看当前详细服务信息,包括master的active和standby信息version 查看版本信息 2、页面查询 http://HMASTERip:16010 #查看master 状态 …...

Android平台RTSP|RTMP播放端实时快照保存JPG还是PNG?

JPG还是PNG&#xff1f; 实际上&#xff0c;在前几天的blog&#xff0c;我们有从压缩方式、图像质量、透明效果、可编辑性等各方面做过差异化的介绍。 压缩方式&#xff1a;JPG是一种有损压缩格式&#xff0c;通过丢弃图像数据来减小文件大小&#xff0c;因此可能会损失一些图…...

【人工智能】之深入了解嵌入模型中的 Token:NLP 中的语义之旅(1)

自然语言处理&#xff08;NLP&#xff09;领域的发展在很大程度上受到了嵌入模型的推动。嵌入模型通过将文本中的每个 token 转换为向量表示&#xff0c;为计算机理解语言提供了强大的工具。本文将深入研究嵌入模型中的 token&#xff0c;揭示它在 NLP 中的重要性以及在语义表示…...

UML-实现图(组件图和部署图)

实现图是从系统的层次来描述的&#xff0c;描述硬件的组成和布局&#xff0c;描述软件系统划分和功能实现。 UML-实现图&#xff08;组件图和部署图&#xff09; 一、组件图1.组件图的元素&#xff08;1&#xff09;组件&#xff08;2&#xff09;接口&#xff08;3&#xff09…...

苹果Find My可查找添加32件物品,伦茨科技ST17H6x芯片加速产品赋能

苹果最近更新的支持文档证实&#xff0c;从 iOS 16 开始&#xff0c;"Find My"可查找添加物品从16件增加到32件&#xff0c;AirTag 和“查找”网络中的物品利用“查找”网络的强大功能来发挥作用&#xff0c;这个网络由数亿台加密的匿名 Apple 设备构成。“查找”网络…...

postman后端测试时invalid token报错+token失效报错解决方案

报错信息1{“msg”:“invalid token”,“code”:401} 没有添加postman的token信息 报错信息2{“msg”: “token失效&#xff0c;请重新登录”,“code”: 401} 写了token但是token信息写的是错的,会提示token失效 解决方案如下 仅写完后端的查询,但是前端还没写的时候,可…...

使用 mybatis-plus 的mybaits的一对多时, total和record的不匹配问题

应该是框架的问题&#xff0c;去官方仓库提了个issues&#xff0c;等回复 https://github.com/baomidou/mybatis-plus/issues/5923 回复来了&#xff1a; 背景 发现 record是两条&#xff0c;但是total显示3 使用resultMap一对多时&#xff0c;三条数据会变成两条&#xff0…...

SpringCloud之Nacos

一、微服务介绍 1. 什么是微服务 2014年,Martin Fowler(马丁福勒 ) 提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通信。同时服务会使用最小的规模…...

小封装高稳定性振荡器 Sg2520egn / sg2520vgn, sg2520ehn / sg2520vhn

描述 随着物联网和ADAS等5G应用的实施&#xff0c;数据流量不断增长&#xff0c;网络基础设施变得比以往任何时候都更加重要。IT供应商一直在快速建设数据中心&#xff0c;并且对安装在数据中心内部/内部的光模块有很大的需求。此应用需要具有“小”&#xff0c;“低抖动”和“…...

使用 Apache POI 更新/覆盖 特定的单元格

使用 Apache POI 更新特定的单元格 一. 需求二. 实现三. 效果 一. 需求 将以下表中第4行&#xff0c;第4列的单元格由“张宇”更新为“汤家凤”&#xff0c;并将更行后的结果写入新的Excel文件中&#xff1b; 二. 实现 使用Apache POI&#xff0c;可以精确定位到需要更改的单…...

Spring Boot整合MyBatis-Plus

引言 在现代软件开发中&#xff0c;我们经常需要处理大量的数据。为了有效地管理这些数据&#xff0c;我们需要使用一些强大的框架。其中&#xff0c;Spring Boot和MyBatis-Plus是两个非常流行的框架。Spring Boot是一个基于Spring的开源Java框架&#xff0c;可以用于创建独立…...

springboot项目之AOP角色权限的判断

引言 开发的项目中&#xff0c;可能遇到不同的角色&#xff0c;不同的角色有不通的权限定义。AOP切面是个很好的解决方案。 实践 1. 定义MerchRoles Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface MerchRoles {} 2. 定义切点 public c…...

Twincat PLC 跳出循环

在TwinCAT PLC编程中&#xff0c;要跳出循环结构通常可以通过以下几种方式实现&#xff1a; 使用Break指令&#xff1a; 在TwinCAT 3的PLC编程环境中&#xff08;IEC 61131-3标准&#xff09;&#xff0c;可以使用BREAK指令来立即终止最内层的循环。例如&#xff0c;在FOR或WH…...

【Leetcode】277.搜寻名人

一、题目 1、题目描述 假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0 到 n - 1 标号。在这个派对人群当中可能存在一位 “名人”。所谓 “名人” 的定义是:其他所有 n - 1 个人都认识他/她,而他/她并不认识其他任何人。 现在你想要确认这个 “名人” 是…...

小白数学建模 Mathtype 7.7傻瓜式下载安装嵌入Word/WPS以及深度使用教程

数学建模Mathtype的下载安装嵌入Word/WPS以及深度使用教程 一 Mathtype 的下载安装1.1 安装前须知1.2 下载压缩包1.3 安装注册 二 嵌入Word/WPS2.1 嵌入Word2.1.1 加载项嵌入 Word2.1.2 宏录制嵌入 Word 2.2 嵌入 WPS2.2.1 加载项嵌入 WPS2.2.2 宏录制嵌入 WPS 2.3 嵌入时报错解…...

Linux之which和find

...

MySQL 常规操作指南

1. 连接MySQL服务器 &#xff08;1&#xff09;通过命令行连接 mysql -u username -p在提示下输入对应用户的密码&#xff0c;即可进入MySQL命令行界面。 &#xff08;2&#xff09;指定数据库连接 mysql -u username -p -D database_name这里会直接连接到名为database_nam…...

Rocketmq rust版本-开篇

我是蚂蚁背大象(Apache EventMesh PMC&Committer)&#xff0c;文章对你有帮助给Rocketmq-rust star,关注我GitHub:mxsm&#xff0c;文章有不正确的地方请您斧正,创建ISSUE提交PR~谢谢! Emal:mxsmapache.com Rust重构Rocketmq,大家好我是mxsm(Apache EventMesh PMC&Comm…...

springboot3+springsecurity6集成druid启动报错

环境&#xff1a;springboot3security6druid1.2.20 druid1.2.20这个版本开始支持springboot3自动配置&#xff0c;不再需要手动引入 依赖为 <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId>…...

golang面试题大全

go基础类 1、与其他语言相比&#xff0c;使用 Go 有什么好处&#xff1f; 与其他作为学术实验开始的语言不同&#xff0c; Go 代码的设计是务实的。每个功能和语法决策都旨在让程序员的生活更轻松。Golang 针对并发进行了优化&#xff0c;并且在规模上运行良好。由于单一的标…...

Google 在裁员的路上一路狂奔

早上刷新闻&#xff0c;Google 在 2024 开年还没几天就宣布了今年的裁员计划。 前几天还在说我们当地的大学为了削减预算而进行裁员。 大厂谷歌却是首当其冲&#xff0c;裁员1000多人&#xff0c;涉及了核心工程、谷歌助理、Pixel手机等硬件团队的人员。 截至2023年9月30日&…...

橘子学K8S04之重新认识Docker容器

我们之前分别从 Linux Namespace 的隔离能力、Linux Cgroups 的限制能力&#xff0c;以及基于 rootfs 的文件系统三个角度来理解了一下关于容器的核心实现原理。 这里一定注意说的是Linux环境&#xff0c;因为Linux Docker (namespaces cgroups rootfs) ! Docker on Mac (bas…...

Day31- 贪心算法part05

一、无重叠区间 题目一&#xff1a;453. 无重叠区间 435. 无重叠区间 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠 。 主要思想是优先保留结束时间早的区间&#xff0c;这样…...

基于springboot+vue的蜗牛兼职网的设计与实现系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…...

【音视频原理】图像相关概念 ② ( 帧率 | 常见帧率标准 | 码率 | 码率单位 )

文章目录 一、帧率1、帧率简介2、常见帧率标准3、帧率 刷新率 二、码率1、码率简介2、码率单位 一、帧率 1、帧率简介 帧率 Frame Rate , 帧 指的是 是 画面帧 , 帧率 是 画面帧 的 速率 ; 帧率 的 单位是 FPS , Frames Per Second , 是 每秒钟 的 画面帧 个数 ; 帧率 是 动画…...

CSS Position总结:定位属性的实战技巧

CSS Position总结&#xff1a;定位属性的实战技巧 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在今天的文章中&#xff0c;我们将深入研究CSS中一个至关重要的属…...

python基础系列二-函数

系统函数 函数说明abs返回一个数的绝对值&#xff0c;例如&#xff1a;abs(-1.3)会返回1.3。bin把一个整数转换成以0b开头的二进制字符串&#xff0c;例如&#xff1a;bin(123)会返回0b1111011。chr将Unicode编码转换成对应的字符&#xff0c;例如&#xff1a;chr(8364)会返回…...

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用短曝光功能(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用短曝光功能&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用短曝光功能1.引用合适的类文件2.通过NEOAPI SDK使用短曝光功能3.通过NEOAPI SDK关闭短…...