第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.hqwc.cn/news/415264.html

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

相关文章

将vue项目打包成桌面客户端实现点击桌面图标直接进入项目

1.下载NW.js 下载地址&#xff1a;NW.js官网 下载完后zip解压 2.文件夹下新建index.html index内容如下&#xff1a; <!DOCTYPE html> <html> <head> </head> <body> <script language"javascript" type"text/javascript&q…

element plus表格的表头和内容居中

文章目录 需求分析 需求 对于 element-plus 中的 table 进行表头和内容的居中显示 分析 单列的表头和内容居中 &#xff1a; 在对应的那一列加上align“center” 即可 <el-table-column prop"name" label"商品名称" align"center" />…

QCustomPlot绘制柱状图,折线图

柱状图绘制 // 创建QCustomPlot对象QCustomPlot customPlot;// 创建柱状图数据QVector<double> xData { 1, 2, 3, 4, 5 };QVector<double> yData { 3, 6, 2, 7, 4 };// 创建柱状图数据容器QCPBars *bars new QCPBars(customPlot.xAxis, customPlot.yAxis);bars…

element中表格组件的row-class-name和class-name属性的使用以及无效处理

1.这两个属性的使用&#xff0c;row-class-name用在el-table标签上&#xff0c;class-name用在el-table-column标签上。两个属性即可绑定类名也可绑定函数 <!-- 这里是绑定函数&#xff0c;也可以绑定类名 --> <el-table :data"tableData" selection-chang…

前端-基础 表格标签 总结

目录 表格的相关标签 &#xff1a; 表格的相关属性 合并单元格 &#xff1a; 表格的相关标签 &#xff1a; 表格标签 - <table> 行标签 - <tr> 单元格标签 - <td> 表头单元格标签 - <th> 表格结构标签 表头区域标签 - < thead >…

HarmonyOS NEXT鸿蒙星河版发布

1月18日,在深圳举行的“鸿蒙生态千帆启航仪式”上,华为常务董事、终端BG CEO余承东宣布HarmonyOS NEXT鸿蒙星河版面向开发者开放申请。鸿蒙星河版将实现原生精致、原生易用、原生流畅、原生安全、原生智能、原生互联6大极致原生体验。 并且,华为在 1 月 15 日开启了HarmonyO…

游戏云化好吗?游戏云化会带来什么?

随着云计算技术的飞速发展&#xff0c;游戏云化成为游戏产业中备受关注的话题。这一新兴技术给玩家和游戏行业带来了全新的可能性。本文将深入探讨游戏云化的概念、优势以及可能带来的影响。 1、什么是游戏云化&#xff1f; 游戏云化是指将游戏的各个环节&#xff0c;包括游戏…

如何使用Portainer部署web站点并实现无公网ip远程访问

文章目录 前言1. 安装Portainer1.1 访问Portainer Web界面 2. 使用Portainer创建Nginx容器3. 将Web静态站点实现公网访问4. 配置Web站点公网访问地址4.1公网访问Web站点 5. 固定Web静态站点公网地址6. 固定公网地址访问Web静态站点 前言 Portainer是一个开源的Docker轻量级可视…

用 Python 制作可视化 GUI 界面,一键实现自动分类管理文件!

经常杂乱无章的文件夹会让我们找不到所想要的文件&#xff0c;因此小编特意制作了一个可视化GUI界面&#xff0c;通过输入路径一键点击实现文件分门别类的归档。 不同的文件后缀归类为不同的类别 我们先罗列一下大致有几类文件&#xff0c;根据文件的后缀来设定&#xff0c;大…

大模型增强大模型:通过融合扩展能力(Google DeepMind2024)

1、写作动机&#xff1a; 存在如此多领域特定的模型自然引发一个问题&#xff1a;我们是否能够将一个固定模型与一个特定领域的增强模型组合&#xff0c;以实现新的能力&#xff1f;例如&#xff0c;我们是否可以将增强模型的代码理解能力与固定LLM的语言生成能力组合&#xf…

【单片机】STM32 ARM Cortex-M0 微控制器特性概述 双排 TSSOP封装好手工焊接的STM32芯片,双排

STM32F070CB STM32F070RB STM32F070C6 STM32F070F6 在嵌入式系统和物联网应用中&#xff0c;ARM Cortex-M0 微控制器以其强大的性能和丰富的功能而备受瞩目。本文将介绍该微控制器的主要特性&#xff0c;使读者更好地了解其适用范围和潜在应用。 核心特性 ARM 32位 Cortex…

Python爬虫---scrapy框架---当当网管道封装

项目结构&#xff1a; dang.py文件&#xff1a;自己创建&#xff0c;实现爬虫核心功能的文件 import scrapy from scrapy_dangdang_20240113.items import ScrapyDangdang20240113Itemclass DangSpider(scrapy.Spider):name "dang" # 名字# 如果是多页下载的话, …