JAVA Socket编程 课堂作业
编写一个Client/Server应用,用于维护一个电话号码本,电话号码本保存在Server端,Client端可以发送两种请求,保存电话号码,其命令格式为:PUT + 一个空格 + 姓名 + 一个空格 + 电话号码;查询电话号码命令,其格式为:GET + 一个空格 + 姓名,姓名和电话号码内都不能有空格。服务器端在接收到客户端的请求后,根据请求完成相应的工作,如果是PUT请求,服务器将把姓名和对应的电话号码保存到一个Map<String, String>类型的变量中,如果是GET,服务器将查询指定姓名的电话号码,服务器将把执行请求的结果发送给客户端。 附录1、2和3中分别有MyServer、MyClient和MultiServer的源代码。MyServer是阻塞型服务器类,无法同时处理多个客户的请求,MyClient用于测试MyServer,其参数(姓名和电话号码等)均直接写在代码中,MultiServer是非阻塞型服务器类的一个例子,使用了多线程技术,可以同时处理多个客户的请求。 根据附件提供的代码,完成以下要求: 1、参考MultiServer类,利用多线程改写类MyServer,使其可以同时处理多个客户的请求(50分)。 2、实现一个类PhoneClient,用于向MyServer提交请求,使其参数(请求命令PUT或者GET,姓名,电话号码)可以通过命令行带入(50分)。比如在命令行: PhoneClient PUT tom 83780909 表示保存tom及其电话号码。 在命令行: PhoneClient GET tom 表示查询tom的电话号码
作业截图:
源码:
---------------------------------------------------MyServer 类---------------------------------------------------
package homework02; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; public class MyServer { public static Map<String, String> phones = new HashMap(); static int clientnum = 0; public static void main(String args[]) throws IOException { ServerSocket ss = null; boolean listening = true; int port = 8000; try { ss = new ServerSocket(port); } catch (IOException e) { System.out.println("Could not listen on port:"+ port +"."); System.exit(-1); } while (listening) { try { new MyServerThread(ss.accept(),clientnum).start(); ++clientnum; } catch (Exception e) { System.out.println("Error:" + e); } } ss.close(); } } class MyServerThread extends Thread{ Socket socket = null; int clientnum; public MyServerThread(Socket socket,int num){ this.socket = socket; clientnum = num+1; } public void run(){ try{ BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter os = new PrintWriter(socket.getOutputStream()); String answer = ""; DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); System.out.println(dateFormat.format(new Date()) + " Client[" + clientnum + "]:" + "Connected"); String request = is.readLine(); while (!request.equals("bye")){ answer = ""; System.out.println(dateFormat.format(new Date()) + " Client[" + clientnum + "]:" + request); String command = request.substring(0, request.indexOf(" ")).trim().toUpperCase(); String para = request.substring(request.indexOf(" ")+1).trim(); if ("GET".equals(command)) { String phone = PhoneServer.phones.get(para); if ( phone!=null) { answer = "SUCCESS " + phone; } else { answer = "FAILURE no phone number for " + para; } } else if ("PUT".equals(command)) { String[] datas = para.split(" "); if (datas.length == 2) { PhoneServer.phones.put(datas[0], datas[1]); answer += "SUCCESS phone number is saved"; } else { answer = "FAILURE" + " parameters error"; } } else { answer = "FAILURE" + " command error"; } System.out.println(dateFormat.format(new Date()) + " Client[" + clientnum + "] [RESULT]:" + answer); os.println(answer); os.flush(); request = is.readLine(); } os.flush(); os.close(); is.close(); socket.close(); }catch (Exception e){ System.out.println("Error: " + e); } } }
---------------------------------------------------PhoneClient类------------------------------------------------
package homework02; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class PhoneClient { public static void main(String args[]) { try { Socket socket = new Socket("127.0.0.1", 8000); PrintWriter os = new PrintWriter(socket.getOutputStream()); BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); String line = sin.readLine(); while(!line.equals("bye")){ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String curTime = dateFormat.format(new Date()); System.out.println(curTime + " Client: " + line); os.println(line); os.flush(); String answer = is.readLine(); System.out.println(dateFormat.format(new Date()) + " Server: " + answer); line = sin.readLine(); } sin.close(); os.close(); is.close(); socket.close(); } catch (Exception e) { System.out.println("Error" + e); } } }
---------------------------------------------------PhoneServer 类------------------------------------------------
package homework02; import java.util.HashMap; import java.util.Map; public class PhoneServer { public static Map<String,String> phones = new HashMap<>(); }
参考资料:
首先java分为节点流和处理流,节点流与节点(可以是物理的,也可以是内存的)相连,比如文件或者String,比如 FileReader fr = new FileReader("foo.bar"),处理流是用来包装节点流的,比如BufferedReader br = new BufferedReader(fr),分为这两种流是为了屏蔽底层节点不 同而造成多余的编码。 其次java又分为字符流和字节流,一般带有InputStream,OutputStream的就是字节流,带有Writer,Reader的就是字符流。字节流要转换成字符流 的话就要用 InputStreamReader,OutputStreamWriter. 看这个问题,getInputStream是得到一个字节的节点流,BufferedReader是个字符的处理流,它包装的需要是个字符的节点流, 于是,用 InputStreamReader转换为字符的流。 总之,需要搞清楚,字符,字节,节点,处理流的区别,前2个一组,后2个一组 https://www.cnblogs.com/redick/p/6644594.html https://blog.csdn.net/ai_bao_zi/article/details/81133476 https://www.jianshu.com/p/705ddc84936d https://blog.csdn.net/qq1175421841/article/details/52411607 java socket: https://www.cnblogs.com/rocomp/p/4790340.html https://blog.csdn.net/fw0124/article/details/41227543