第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.mzph.cn/news/632657.shtml

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

相关文章

Qt程序如何在Release模式下进行断点调试

有些时候,因为某些工程pro文件设置了debug和Release版本的原因,导致在编译运行的时候,程序会自动生成带d后缀的一些库文件,进行调试。 debug模式下我们打断点进行调试,大家都知道。但是Release模式下,如果你直接Ctrl + R运行,肯定是无法断点调试的。 那么这个时候,我…

AEB滤镜再破碎,安全焦虑「解不开」?

不久前&#xff0c;理想L7重大交通事故&#xff0c;再次引发了公众对AEB的热议。 根据理想汽车公布的事故视频显示&#xff0c;碰撞发生前3秒&#xff0c;车速在178km/h时驾驶员采取了制动措施&#xff0c;但车速大幅超出AEB&#xff08;自动紧急刹车系统&#xff09;的工作范…

如何搭建Z-blog网站并结合内网穿透实现无公网ip访问本地站点

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…

hadoop下载,安装

下载&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/ 从清华源下载 找到apache 找到hadoop 找到对应的版本 使用64位版本 上传到linux的 /usr/local 目录下 使用tar -zxvf 文件。 命令解压 添加path路径 1&#xff0c;vim /etc/profile 2, 追加hadoop的两个bin路径…

Ps:使用钢笔工具快速精准抠图的技巧

众所周知&#xff0c;钢笔工具是 Photoshop 中最精准的、适用于硬边缘&#xff08;清晰轮廓&#xff09;对象的抠图工具。但是&#xff0c;如果从头开始一个锚点一个锚点的勾勒&#xff0c;既费时又费眼。 我们可以先用选区工具或选区命令做一个基础选区&#xff0c;然后将选区…

【Linux】权限的深度解析

前言&#xff1a;在此之前我们学习了一些常用的Linux指令&#xff0c;今天我们进一步学习Linux下权限的一些概念 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:Linux的学习 &#x1f448; &#x1f4af;代码仓库:卫卫周大胖的学习日记&a…

python实现图片式PDF转可搜索word文档[OCR](已打包exe文件)

目录 1、介绍 1.1、痛点 1.2、程序介绍 2、安装方式 2.1、&#x1f53a;必要环节 2.2、脚本安装 2.2.1、不太推荐的方式 2.2.2、节约内存的方式 2.3、⭐完整版安装 3、使用 3.1、最终文件目录 3.2、主程序 3.2.1、绝对路径 3.2.2、是否为书籍 3.2.3、⭐截取区域 …

lvgl移植流程

移植准备 基于梁山派屏幕扩展板mcu屏幕源码Screen_MCU移植下载lvgl 8.3版本源码下载地址:https://github.com/lvgl/lvgl参考文档:Set-up a project — LVGL documentation 移植步骤 1. 删除源码 删除源码中不需要的文件夹&#xff0c;仅保留如下内容 demos : lvgl综合案例e…

QtCreator12无法识别Qt5.15.2的安卓SDK与NDK配置解决

解决方法: 设置JDK为JDK11 使用Android Studio下载 Android SDK Command-line Tools 10.0 打开Android SDK Location : 双击打开cmdline-tools 复制10.0中所有东西到latest中 点击Manage Kits并选择Devices 然后点击Android会弹出下图窗口,并自动更 安装完成 成功识别

股票套牢,如何解套?当下行情怎么赚钱?

今年开年大盘继续一路下行&#xff0c;今天更是直接跌破2800点&#xff0c;很多朋友都是套牢的阶段&#xff0c;这种时候我们怎样解套&#xff0c;在这种情况下&#xff0c;作为散户的我们又如何才可以赚到钱呢&#xff1f; 股票被套可以借用哪些工具解套&#xff1f;详细操作…

新数智空间:阿里云边缘云持续保持中国公有云市场第一

全球领先的 IT 市场研究和咨询公司 IDC 发布 《中国边缘云市场解读&#xff08;2023H1&#xff09;》报告 中国边缘公有云服务市场 阿里云持续第一 稳居市场第一&#xff0c;“边缘”逆势生长 近日&#xff0c;全球领先的 IT 市场研究和咨询公司 IDC 最新发布《中国边缘云市…

Git学习笔记(第2章):Git安装

官网地址&#xff1a;Githttps://git-scm.com/ Step1&#xff1a;查看Git的GNU协议 → 点击“Next” Step2&#xff1a;设置Git的安装位置(非中文、无空格的目录) → 点击“Next” Step3&#xff1a;选择Git的选项配置(推荐默认设置) → 点击“Next” Step4&#xff1a;设置Git…

POI实现Excel多行复杂表头导出

POI实现Excel多行复杂表头导出 1. pom文件添加POI相关依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.10-FINAL</version> </dependency> <dependency><groupId>o…

python代码练习:链表——分隔链表

参考知识&#xff1a; 什么是链表Optional有什么用 题目&#xff1a; 题目来源&#xff1a;力扣 代码&#xff1a; from typing import Optionalclass ListNode: 链表结点的数据类型 def __init__(self, val0,nextNone):self.val valself.next nextdef convert_to_linked…

index_jsp报错

今天跟着视频一模一样敲代码&#xff0c;一直报500 搜索了好几篇csdn&#xff0c;不断地修改添加的jstl.jar 和standard.jar&#xff0c;修改这两个jar包版本&#xff0c;还是报500 又看到说是因为tomcat10中存在jsp.jar&#xff0c;同时存在发生冲突&#xff0c;于是把tomcat…

字符型在内存中的存储

由于此字符型只占一个字节 所以它就不存在大端存储和小端存储。 字符型数据在内存中的存储的是ASCII码值转换成的二进制的补码&#xff08;有符号char的二进制也有原码&#xff0c;反码&#xff0c;补码之分&#xff09; 例 ↑的十进制的ASCII值为24 转换成二进制为00011000…

docker里Java服务执行ping命令模拟流式输出

文章目录 业务场景处理解决实现ping功能并实时返回输出实现长ping和中断请求docker容器找不到ping命令处理 业务场景 我们某市的客户&#xff0c;一直使用CS版本的信控平台&#xff0c;直接安装客户Windows server服务器上&#xff0c;主要对信号机设备进行在线管理、方案配时…

Peter:经济形势不好,一个最大的原因就是诚信道德的缺失 | 程客有话说002

《程客有话说》是我们最新推出的一个访谈栏目&#xff0c;邀请了一些国内外有趣的程序员来分享他们的经验、观点与成长故事&#xff0c;我们尝试建立一个程序员交流与学习的平台&#xff0c;也欢迎大家推荐朋友或自己来参加我们的节目&#xff0c;一起加油。本期我们邀请的程序…

实验一 安装和使用Oracle数据库

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

基于人工蚁群、蚁群、遗传算法的多目标任务分配

matlab2020a可运行 基于人工蚁群、蚁群、遗传算法的多目标任务分配资源-CSDN文库