第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();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/241305.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【02】mapbox js api加载arcgis切片服务

需求&#xff1a; 第三方的mapbox js api加载arcgis切片服务&#xff0c;同时叠加在mapbox自带底图上 效果图&#xff1a; 形如这种地址去加载&#xff1a; http://zjq2022.gis.com:8080/demo/loadmapbox.html arcgis切片服务参考链接思路&#xff1a;【01】mapbox js api加…

java.lang.UnsupportedOperationException: null 其一解决办法

文章目录 前言一、错误回顾1.详细信息2.代码详情 二、解决方案1.错误原因2.解决方案1.使用 new ObjectMapper() new TypeReference<List>(){}2.使用 SerializerFeature.WriteMapNullValue.getMask() 总结 前言 当我们远程调用传递泛型集合&#xff0c;如 List<?>…

Angular系列教程之观察者模式和RxJS

文章目录 引言RxJS简介RxJS中的设计模式观察者模式迭代器模式 示例代码RxJS 在 Angular 中的应用总结 引言 在Angular开发中&#xff0c;我们经常需要处理异步操作&#xff0c;例如从后端获取数据或与用户的交互。为了更好地管理这些异步操作&#xff0c;Angular中引入了RxJS&…

JOSEF约瑟 过电流继电器JL12-40A 线圈额定电流40A 柜内安装

系列型号 JL12-15A电流继电器JL12-20A电流继电器 JL12-30A电流继电器JL12-40A电流继电器 JL12-60A电流继电器JL12-75A电流继电器 JL12-100A电流继电器JL12-150A电流继电器 JL12-200A电流继电器JL12-300A电流继电器 一、概述 过流继电器JL12-40A适用于电压为380V&#xff…

C++系列-第1章顺序结构-9-字符类型char

在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 总结 本文是C系列博客&#xff0c;主要讲述字符类型char 字符类型char 在C编程语言中&#xff0c;char是一种基本的数据类型&#xff0c;它用于存储单个字符。字符可以是字母、数字、标点符号或者…

计算机网络-ACL访问控制列表

上一篇介绍NAT时候就看到了ACL这个东西了&#xff0c;这个是什么意思&#xff1f;有什么作用呢&#xff1f; 一、ACL访问控制列表 访问控制列表 (ACL, Access Control List)是由一系列permit或deny语句组成的、有序规则的列表。ACL是一个匹配工具&#xff0c;能够对报文进行匹配…

C语言--质数算法和最大公约数算法

文章目录 1.在C语言中&#xff0c;判断质数的常见算法有以下几种&#xff1a;1.1.试除法&#xff08;暴力算法&#xff09;&#xff1a;1.2.优化试除法&#xff1a;1.3.埃拉托色尼筛法&#xff1a;1.4.米勒-拉宾素性检验&#xff1a;1.5.线性筛法&#xff1a;1.6.费马小定理&am…

Android Activity的启动流程(Android-10)

前言 在Android开发中&#xff0c;我们经常会用到startActivity(Intent)方法&#xff0c;但是你知道startActivity(Intent)后Activity的启动流程吗&#xff1f;今天就专门讲一下最基础的startActivity(Intent)看一下Activity的启动流程&#xff0c;同时由于Launcher的启动后续…

Spring Boot整合JUnit

引言 测试是软件开发过程中不可或缺的一环&#xff0c;而JUnit作为Java生态中最流行的测试框架之一&#xff0c;与Spring Boot的整合为开发者提供了一套强大的测试工具。本文将讨论Spring Boot整合JUnit的技术细节、最佳实践以及测试驱动开发&#xff08;TDD&#xff09;的优雅…

Android: alarm定时很短时,比如500ms,测试执行mPowerManager.forceSuspend()后,系统不会suspend

参考文档&#xff1a; https://blog.csdn.net/weixin_35691921/article/details/124961404 Android: alarm定时很短时&#xff0c;比如500ms&#xff0c;然后执行mPowerManager.forceSuspend()后&#xff0c;系统不会suspend&#xff0c;原因分析&#xff1a; static int ala…

数学建模--比赛

内容来自数学建模BOOM&#xff1a;【快速入门】北海&#xff1a;数模建模基础MATLAB入门论文写作数学模型与算法(推荐数模美赛国赛小白零基础必看教程)_哔哩哔哩_bilibili 目录 1.学习内容 2.参赛须知 1&#xff09;参赛作品的组成 2)参赛作品的提交 3.软件安装 4.注意…

Python实战 -- PySide6 制作天气查询软件

一、环境准备 开发环境&#xff1a;Python 3.9.2 pycharm PySide6 申请天气情况 API &#xff1a;https://console.amap.com/dev/key/app designer 设计 ui 目录下 Weather.ui 转换为 Weather.py 结果显示 二、完整代码 import sysfrom PySide6 import QtWidgetsimport…

制造业企业数字化转型难点剖析及解决之法

导语 全球正在由工业经济向数字经济转型过渡&#xff0c;制造业正在且并将长期处于数字化转型发展阶段&#xff0c;并沿着数字化、网络化、智能化阶段不断跃升。但如何找准数字化转型的切入点&#xff0c;以低耗能、低成本、高效率的方式加快制造业转型升级的步伐&#xff0c;仍…

MySQL 索引(上)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL-进阶篇 &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现…

Docker五部曲之五:通过Docker和GitHub Action搭建个人CICD项目

文章目录 项目介绍Dockerfile解析compose.yml解析Nginx反向代理到容器以及SSL证书设置MySQL的准备工作Spring和环境变量的交互 GitHub Action解析项目测试结语 项目介绍 该项目是一个入门CICD-Demo&#xff0c;它由以下几部分组成&#xff1a; Dockerfile&#xff1a;用于构建…

像操作本地文件一样操作linux文件 centos7环境下samba共享服务搭建详细教程

1.安装dnf yum -y install dnf 2.安装samba dnf install samba -y 3.配置 3.1创建并设置用户信息 #创建用户 useradd -M -s /sbin/nologin samba echo 123|passwd --stdin samba mkdir /home/samba chown -R samba:samba /home/samba smbpasswd -a samba smaba设置密码示…

Dobbo --- HelloWorld项目搭建

Dobbo-HelloWorld 1. demo -- spring方式集成1.1 实现步骤 2. demo -- springboot方式集成2.1 实现provider2.2 实现consumer2.3 项目测试 1. demo – spring方式集成 dubbo官方文档 提供一个可被调用的接口 提供方&#xff1a;实现接口的方法逻辑&#xff0c;启动应用程序&a…

跨境电商多语种服务指南:如何提供优质的客户体验?

卓越的客户支持是成功企业的核心&#xff0c;客户希望得到全天候的及时响应。根据《哈佛商业评论》的研究报告&#xff0c;快速及时地响应会促使人们在未来支付更多的费用。而在与全球客户打交道时&#xff0c;特别是跨境电商企业&#xff0c;您的沟通必须超越语言障碍。用客户…

Python爬虫 - 网易云音乐下载

爬取网易云音乐实战&#xff0c;仅供学习&#xff0c;不可商用&#xff0c;出现问题&#xff0c;概不负责&#xff01; 分为爬取网易云歌单和排行榜单两部分。 因为网页中&#xff0c;只能显示出歌单的前20首歌曲&#xff0c;所以仅支持下载前20首歌曲&#xff08;非VIP音乐&…

【笔记】Helm-3 主题-6 Chart仓库指南

Chart仓库指南 本节介绍如何创建和使用chart仓库。在高层级中&#xff0c;chart仓库是打包的chart存储和分享的位置。 社区的Helm chart仓位于 Artifact Hub &#xff0c;欢迎加入。不过Helm也可以创建并运行您自己的chart仓库。该指南将介绍如何操作。 Artifact Hub 先决条…