1.实现图形、图片、信息的发送,首先写了一个服务器的界面,在界面上给按钮添加了ActionListener 的监听器,目的是为了写一个判断的标志区别画线,画圆及发送图片的功能.然而,服务器发送直线和圆我是另外创建了一个鼠标监听器MouseListener,每当释放鼠标的时候根据前面的判断标志画一条线或是或一个圆.
2.值得注意的是画完一条线或是画完一个圆后就发送出去.假如要是等着线或是圆都画完了才发送这就会出现问题,比如说服务器要判断到底什么时候才能画完线以及圆,还有一点就是画线和画圆与发送消息不同的地方时,在定义消息发送的时候我是定义的一个字节一个字节的发送,而在发送直线、圆的时候定义的是发送5个int,第一个int判断发送的图形,后面4个int是为了保证有两点坐标表实现画线画圆的操作.发送图片也是类似的操作,每次发送四个int,第一个int实现判断发送的是图片,第二个int发送的是颜色rgb=image.getRGB(i,j);,后面两个int实现画一个点.代码如下:
public void mouseReleased(MouseEvent e) { x2 = e.getX(); y2 = e.getY(); //判断画直线 if(type == 1){ g.drawLine(x1,y1,x2,y2);//画出一条直线 ChatList.sendIntMg(1);//服务器的信息为1发送一条直线 ChatList.sendIntMg(x1); ChatList.sendIntMg(y1); ChatList.sendIntMg(x2); ChatList.sendIntMg(y2); System.out.println("画直线的方法执行了!!!"); } //判断画圆 if(type == 2){ g.drawOval(x1,y1,Math.abs(x2-x1),Math.abs(y2-y1));//画一个圆 ChatList.sendIntMg(2);//服务器的信息为2发送一个圆 ChatList.sendIntMg(x1); ChatList.sendIntMg(y1); ChatList.sendIntMg(x2); ChatList.sendIntMg(y2); System.out.println("画圆的方法执行了!!!"); }
3.发送图片的方法如下:通过一个按钮先实现了将图片画到自定义的面板上,画好后执行的操作还是即刻发送
if(e.getActionCommand().equals("发图")){ System.out.println(e.getActionCommand()); try { BufferedImage image = ImageIO.read(new File("images/桌面.png"));//存入一张图片 System.out.println("图片存放了!"); int w = image.getWidth();//得到图片的宽度 int h = image.getHeight();//得到图片高度 //遍历图片上的每一个像素点 for(int i=0;i<w;i++){ for(int j=0;j<h;j++){ rgb = image.getRGB(i, j);//图片上去的像素点 Color cl = new Color(rgb); g.setColor(cl);//画笔的颜色 //画图片其实就是画点 g.drawLine(i, j, i, j); //画出图片后就进行发送 ChatList.sendIntMg(4); ChatList.sendIntMg(i); ChatList.sendIntMg(j); ChatList.sendIntMg(rgb); } } } catch (IOException e1) { e1.printStackTrace(); } }
4.在图形以及信息发送之前首要的是给服务器定义一些方法,总的来说大的发面无非就是接收消息以及发送消息了.
(1)当点击服务器上的端口按钮时,实现服务器接收消息
//服务器接收消息的 方法 public void acceptMsg(){ //服务器接收消息 String strread = readString(ins); while(!strread.equals("exit")){ System.out.println("服务器: \r\n"+strread); String sin = "客户端: \r\n"+strread;//客户端收到的消息 byte [] byt = sin.getBytes(); ChatList.sendMsg(byt); jta.setText("客户端: \r\n"+sin); strread = readString(ins); }
(2)服务器发送消息,每次发送一个字节
//服务器群发消息的方法 public void sendAll(byte [] by){ try { dao.write(by); dao.flush(); } catch (IOException e) { e.printStackTrace(); } }
(3)服务器读取直线,其实质就是每次都读到一个int值
//服务器接收直线 public void readLine(){ try { x1 = dai.readInt(); y1 = dai.readInt(); x2 = dai.readInt(); y2 = dai.readInt(); g.drawLine(x1,y1,x2,y2); } catch (IOException e) { e.printStackTrace(); } }
(4)服务器接收到画圆的方法与画线的方法类似,也是每次读到一个int字节
//服务器接收圆的方法 public void readCycle(){ try { x1 = dai.readInt(); y1 = dai.readInt(); x2 = dai.readInt(); y2 = dai.readInt(); g.drawOval(x1,y1,Math.abs(x2-x1),Math.abs(y2-y1)); } catch (IOException e) { e.printStackTrace(); } }
(5)服务器读取到发送图片的方法
//定义接收图片的方法 public void readpicture(){ try { i = dai.readInt(); j = dai.readInt(); //画图片 g.drawLine(i,j,i,j); } catch (IOException e) { e.printStackTrace(); } }
(6)既然有了接收int相当于每次读到四个字节的方法,当然要有发送int的方法了
//定义一个服务器发int的方法 public void sendInt(int flag){ try { dao.writeInt(flag); System.out.println("发送flag:"+flag); dao.flush(); } catch (IOException e) { e.printStackTrace(); } }
(7)为了简便期间以及便易其他地方调用最后定义了一个方法将上述方法包装到一个方法里面
//定义一个服务器与客户端连接的方法 public void towork(java.net.Socket client){ try { //获取输入输出流 ins = client.getInputStream(); ous = client.getOutputStream(); dai = new DataInputStream(ins);//创建一个读入数据的对象 dao = new DataOutputStream(ous);//创建一个写数据的对 //设置判断标识符 int flag = dai.read(); while(true){ System.out.println("读出的flag是: "+flag); //当读到1的时候画线 if(flag == 1){ readLine(); } //当读到2的时候画圆 if(flag == 2){ readCycle(); } //当读到3的时候发送消息 if(flag == 3} acceptMsg(); } if(flag == 4){ readpicture(); } flag = dai.readInt();//读取多个信息 } } catch (IOException e) { e.printStackTrace(); } }
5.自己的理解就是其实当服务器与客户端进行连接之后就相当于可以把客户端也看做成服务器所以说,客户端界面的方法与服务器的方法是类似的这里就不一一列举了.不过,我单独用另外的一个类定义了客户端的方法了.与服务器的方法有一点区别的是我定义了一个客户端的连接方法,实现如下:
//定义服务器与客户端连接的方法 public boolean Connect(){ try { //创建客户端与服务器连接的对象 java.net.Socket soclient = new java.net.Socket(this.ip,this.port); System.out.println("客户端与服务器连接成功了!!!"); //获取输入输出流 ins = soclient.getInputStream(); ous = soclient.getOutputStream(); //数据输入输出流 dai = new DataInputStream(ins); dao = new DataOutputStream(ous); System.out.println("Connect方法执行了!!!"); return true; } catch (Exception e) { e.printStackTrace(); } return false }
6.在此,附上服务器界面的代码客户端的于此类似
package cgh20130730通信发送图形; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; /** * 创建一个服务器界面类继承自JFrame * @author Allen * */ public class ServerUI extends JFrame { /** * 程序的入口主函数 * @param args */ public static void main(String[] args) { //创建对象调用窗体初始化的方法 ServerUI sr = new ServerUI(); sr.INtUI(); } private int x1,y1; private int x2, y2;//坐标属性 private int nport; private int type; private DataInputStream dai; private DataOutputStream dao; private Graphics g; private int rgb; //初始化一个窗体 public void INtUI() { this.setTitle("服务器"); this.setSize(700,650); this.setLocationRelativeTo(null); this.setResizable(false); //设置窗体的流式布局 this.setLayout(new FlowLayout()); //创建按钮对象 JButton jbu = new JButton("端口"); JButton jbu1 = new JButton("发送"); //创建文本框对象 final JTextField jte = new JTextField(30); final JTextField jte1 = new JTextField(30); //创建一个纯文本多行区域 final JTextArea jta = new JTextArea(); jta.setPreferredSize(new Dimension(650,200)); //添加到窗体 this.add(jbu); this.add(jte); this.add(jbu1); this.add(jte1); this.add(jta); //创建一个面板对象 JPanel jpa = new JPanel(); jpa.setPreferredSize(new Dimension(650,350)); jpa.setBackground(Color.GRAY); JButton jbu2 = new JButton("画线"); JButton jbu3 = new JButton("画圆"); JButton jbu4 = new JButton("发图"); jpa.add(jbu2); jpa.add(jbu3); jpa.add(jbu4); //添加面板 this.add(jpa); //显示窗体是否可见 this.setVisible(true); //取得面板上的画布 final Graphics g = jpa.getGraphics(); //动作监听器 ActionListener action = new ActionListener(){ public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("端口")){ nport = Integer.parseInt(jte.getText()); //创建一个服务器类的对象 Server ser = new Server(9007,jta,dao,g); ser.start(); System.out.println("端口号是:==="+nport); } if(e.getActionCommand().equals("发送")){ String strn = jte1.getText(); jta.append("服务器: \r\n"+strn+"\r\n"); ChatList.sendMsg(strn.getBytes()); ChatList.sendIntMg(3); //发完后清空文本 jte1.setText(""); } /* * 画线以及画圆的协议 */ if(e.getActionCommand().equals("画线")){ type = 1; } if(e.getActionCommand().equals("画圆")){ type = 2; } if(e.getActionCommand().equals("发图")){ System.out.println(e.getActionCommand()); try { BufferedImage image = ImageIO.read(new File("images/桌面.png"));//存入一张图片 System.out.println("图片存放了!"); int w = image.getWidth();//得到图片的宽度 int h = image.getHeight();//得到图片高度 //遍历图片上的每一个像素点 for(int i=0;i<w;i++){ for(int j=0;j<h;j++){ rgb = image.getRGB(i, j);//图片上去的像素点 Color cl = new Color(rgb); g.setColor(cl);//画笔的颜色 //画图片其实就是画点 g.drawLine(i, j, i, j); //画出图片后就进行发送 ChatList.sendIntMg(4); ChatList.sendIntMg(i); ChatList.sendIntMg(j); ChatList.sendIntMg(rgb); } } } catch (IOException e1) { e1.printStackTrace(); } } } }; jbu.addActionListener(action); jbu1.addActionListener(action); jbu2.addActionListener(action); jbu3.addActionListener(action); jbu4.addActionListener(action); //面板上添加监听器 MouseListener mouse = new MouseListener(){ public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { x1 = e.getX(); y1 = e.getY(); } public void mouseReleased(MouseEvent e) { x2 = e.getX(); y2 = e.getY(); //判断画直线 if(type == 1){ g.drawLine(x1,y1,x2,y2);//画出一条直线 ChatList.sendIntMg(1);//服务器的信息为1发送一条直线 ChatList.sendIntMg(x1); ChatList.sendIntMg(y1); ChatList.sendIntMg(x2); ChatList.sendIntMg(y2); System.out.println("画直线的方法执行了!!!"); } //判断画圆 if(type == 2){ g.drawOval(x1,y1,Math.abs(x2-x1),Math.abs(y2-y1));//画一个圆 ChatList.sendIntMg(2);//服务器的信息为2发送一个圆 ChatList.sendIntMg(x1); ChatList.sendIntMg(y1); ChatList.sendIntMg(x2); ChatList.sendIntMg(y2); System.out.println("画圆的方法执行了!!!"); } } }; jpa.addMouseListener(mouse);//面板添加监听器 } }
7.简单总结一下该过程中遇到的问题:
(1)服务器发送直线和圆经过测试没有问题可以发送出去,但是在客户端一直显示不出来,原来是自己在定义客户端接收方法的时候出现了一些小问题
(2)服务器可以向客户端发送消息,而反过来的操作就没法实现,最后发现了服务器的方法里面,自己吧read()字节的方法,写成而来readInt()了,因为每次发送的时候自己定义的是发送一个字节
(3)在写完这个程序的时候还有不足的地方就是还没有实现客户端发送直线圆及图片的服务器的方法.
(4)到此结束,希望大家能够多多指正代码中的不足......