上文提到,建立了OrderUI,因为餐馆数增加,所以选择参观时,用number表示选择的餐馆编号,在Mypanel类绘制送给哪个餐馆时,只要向那家餐馆方向移动就行。
run方法修改成
while(xg.flag0==0) { try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //改成number xg.delivey(rest[number].x, rest[number].y); repaint(); }
接下来就进行比较重要的一步:给XiaoGe类建立服务端,OrderUI类建立客户端。
先给XiaoGe类添加窗口与文本域,定义多个属性
//自带缓冲区的输入流public BufferedReader reader;//输出流public PrintWriter writer;//发送的信息public String sendmessage;public transient JFrame frame1=new JFrame("风里雨里的小哥");public transient JTextArea text=new JTextArea(20,20);public transient JPanel panel1=new JPanel();//两个按钮 一个发送消息 一个清空文本域public transient JButton button1=new JButton("send");public transient JButton button2=new JButton("clear");//滚动带public transient JScrollPane roll;
在构造方法中添加
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//改变窗口的布局方式 frame1.setLayout(new FlowLayout()); frame1.setSize(400,400); frame1.setVisible(true); frame1.setBounds(50, 100, 400, 400); //自动换行 text.setLineWrap(true); //构造方法的参数为文本域类 roll=new JScrollPane(text); //定义垂直滚动 roll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); roll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); //面板添加的是滚动带 panel1.add(roll); //以内部类的方式给按钮注册监听 button2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub //清空消息栏 text.setText(""); } }); button1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub //将文本域中的内容发送出去 writer.println(text.getText()); //清空输出流 writer.flush(); text.setText(""); text.requestFocus(); } }); frame1.add(panel1); frame1.add(button2); frame1.add(button1);
启动服务端方法
//开始服务端public void StartKH() { try { //服务端套节字 //端口为5056 ServerSocket serversock=new ServerSocket(5056); //接受客户端信息 while(true) { //有客户才会往下进行 不然会阻塞 Socket socket=serversock.accept(); System.out.println("连接成功"); //输出向客户端 writer=new PrintWriter(socket.getOutputStream()); //读取客户的线程 Thread t=new Thread(new readerCient(socket)); t.start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
不断读取信息的线程(以内部类的方式建立)
//客户端信息要不断读取//所以要建立一个线程实时读取客户端信息class readerCient implements Runnable{//套节子类型 Socket socket; boolean volog=true;//判断是否送餐 public readerCient(Socket UIsocket) { super(); try { socket = UIsocket; //装饰模式读取信息 reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }} @Override public void run() { // TODO Auto-generated method stub String str; //读取信息 try { //有信息开始读取 每次读取一行 while((str=reader.readLine())!=null) { // System.out.println("开始读取"); text.append(str+"\n"); //收到消息 向客户端反馈 if(volog) { writer.println("我已收到,开始送餐"); volog=false; } //必须要加这条语句 不然可能消息发送不成功 writer.flush(); // System.out.println("服务器发送"); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
由于服务端要独立运行,也就是要有自己的main方法,而在Mypanel类中又要获取XiaoGe的位置等信息。所以我想到的解决办法是将XiaoGe类对象序列化,然后在Mypanel类中解序列化(有些不能序列化的类要加transient)。
public static void main(String[] args) { try { //将对象序列化 XiaoGe x1=new XiaoGe(50, 60); ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream("ObjectXiaoGe.txt")); os.writeObject(x1); os.close(); //开始客户端线程 x1.StartKH(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
相应的在Mypanel类中解序列化
//读取对象 try { FileInputStream file=new FileInputStream("ObjectXiaoGe.txt"); ObjectInputStream is = null; if(file.available()!=0) { is=new ObjectInputStream(file); xg=(XiaoGe)is.readObject(); } is.close();
给OrderUI搭建客户端
private void KehuStart() { try { //ip地址与端口 端口要和服务端相同 //"127.0.0.1"代表本机地址 socket=new Socket("127.0.0.1",5056); System.out.println("客户端连接"); //装饰模式 接收服务器消息 reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); //发送消息到服务端 writer=new PrintWriter(socket.getOutputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
同时给客户端不断读取的线程
//不断读取线程class InReader implements Runnable{ String str; @Override public void run() { // TODO Auto-generated method stub try { //System.out.println("wohuizhixing"); //System.out.println(reader.readLine().isEmpty()); while((str=reader.readLine())!=null) { //System.out.println("客服端读取"); text.setText(str); //System.out.println("sufferful"); } //while语句后的不运行 System.out.println("真的会?"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
先启动服务端,再启动客户端,顺序反了会报异常。
如果成功了就会显示下图