编写一个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个一组