java之通信之初接触之小感,附上及其简单网络画板的代码
ServerSocket server=new ServerSocket(8023);System.out.println("服务器创建成功!"+port);
?第二步:当服务器创建成功后,让服务器进入等待状态,等待其它的客户机来连结:
//在等待客户机连结进入,进入后,生成一个Socket对象java.net.Socket client=server.accept();System.out.println("Incoming "+client.getRemoteSocketAddress());
?第三步:从Socket连结对象上调用方法得到输入输出流:
java.net.Socket client=server.accept();//从连结对象上得到输入/输出流对象OutputStream out=client.getOutputStream();InputStream ins=client.getInputStream();
?
客户端创建
Socket client=new Socket(“服务器IP”,服务器端口);
?
? ? ?在谈谈对编写这个网络画板过程吧,最初的想法是做成一个聊天登录界面,可以发送消息,然后输入框为空的时候点击“Send”按钮是就会弹出一个窗体,客户端此时也会弹出与服务器属性相同的窗体,然后就可以在窗体上绘图,然后客户端显示的图形与服务器画的一样。
?
expectation:
?但是,理想很丰满,现实很骨感...于是在各个文件传参的时候出现的如下的情况...
?
reality:
?
?
?
?于是就从各个文件中找各个参数,逐一地测试,输出,特别是从监听器中传参出来,简直就是一个恶魔在心头萦绕。有几个参数传到目的文件要经过几个文件,这也难怪会出现上述问题,这么多文件总有那么几个文件会出问题...
?
? ? ?最后,采取了一个比较折中的方式,就是暂时取消了发送消息的功能和登录验证的功能,以后有必要再加上去,添加了菜单栏,并将绘图命令集成在菜单项中。
?
?
?
? ? ? 再感悟:经过这次简单网络画板的设计,我感到自己在模块整合方面还有待提高,自己写的代码与“搞内聚,低耦合”的理念有一定的距离,但我相信这将会是一个好的开始,并将激励我们发展优秀的设计思路,合理的软件布局。我也相信经过时间的洗礼,骨感的现实终将丰满起来、、、
?
?
?
简单网络画板代码
package com.netBord20130729;import java.awt.Color;import java.awt.Desktop;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.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.URI;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JSeparator;/** * 简单网络画板服务器端 * 界面+通信 * 继承自Thread线程类,实现MouseListener接口 * @author YangKang * */public class NetDrawBordServer extends Thread implements MouseListener{//定义属性,用来存储按下和释放的坐标值private int x1;private int y1;private int x2;private int y2;private int port = 8023;//服务器端口号private ServerSocket server;//服务器private Graphics g;//画布对象private OutputStream ous;//输出流对象private InputStream ins;//输入流对象private DataOutputStream dous;//数据输出流private DataInputStream dins;//数据输入流private Socket client;//客户端private byte type;//绘制图形的类型private String drawCmd = "null";//菜单命令 //定义入口主函数public static void main(String args[]) {NetDrawBordServer ndbs = new NetDrawBordServer();ndbs.GUI();ndbs.Conn2Client();}/** * 创建一个窗体,作为服务器端的画板 */private void GUI() {JFrame netBord = new JFrame();netBord.setTitle("网络画板服务器端");netBord.setSize(new Dimension(600,500));netBord.setDefaultCloseOperation(0);//设置默认关闭操作为不执行任何操作netBord.setLocationRelativeTo(null);netBord.setLayout(new FlowLayout(FlowLayout.LEFT));//设置窗体布局方式为流式布局//添加窗体左上角及最小化的图标ImageIcon frame_icon =new ImageIcon("netPic/0.jpg");netBord.setIconImage(frame_icon.getImage());//添加一个退出确认弹出框,前面定义关闭方式为0netBord.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e) {if(JOptionPane.showConfirmDialog(null,"是否退出")==JOptionPane.OK_OPTION){System.exit(0);}}});//创建菜单条JMenuBar menuBar = new JMenuBar();//创建菜单JMenu menuF = new JMenu("文件(F)");//添加菜单项JMenuItem newItem = new JMenuItem("新建(N)");JMenuItem openItem = new JMenuItem("打开(O)");JMenuItem saveItem = new JMenuItem("保存(S)");//实例化一个水平分隔符对象JSeparator jse = new JSeparator();JMenuItem exitItem = new JMenuItem("退出(E)");//将菜单添加到窗体中netBord.add(menuBar);//菜单添加到菜单条menuBar.add(menuF);//将菜单项添加到菜单menuF.add(newItem); menuF.add(openItem); menuF.add(saveItem); menuF.add(jse); menuF.add(exitItem); JMenu menuE = new JMenu("编辑(E)"); JMenuItem drawLine = new JMenuItem("画直线(L)");JMenuItem drawOval = new JMenuItem("画椭圆(O)");JMenuItem drawRect = new JMenuItem("画矩形(R)");JMenuItem drawTri = new JMenuItem("画三角形(T)");menuBar.add(menuE);menuE.add(drawLine);menuE.add(drawOval);menuE.add(drawRect);menuE.add(drawTri);JMenu menuH = new JMenu("帮助(H)");JMenuItem aboutItem = new JMenuItem("关于(A)");menuBar.add(menuH);menuH.add(aboutItem);//给菜单项添加动作监听器,menuListener为内部监听器openItem.addActionListener(menuListener);saveItem.addActionListener(menuListener);exitItem.addActionListener(menuListener);drawLine.addActionListener(menuListener);drawOval.addActionListener(menuListener);drawRect.addActionListener(menuListener);drawTri.addActionListener(menuListener);aboutItem.addActionListener(menuListener);//最后加上set语句可以将菜单栏添加到窗体顶部netBord.setJMenuBar(menuBar);netBord.setVisible(true);//在窗体可见之后,获取画布的对象g = netBord.getGraphics();//给窗体添加鼠标监听器netBord.addMouseListener(this);}/** * 菜单栏内部监听器,用于将采集所有菜单栏的命令 */ActionListener menuListener = new ActionListener() {public void actionPerformed(ActionEvent e) {String cmd = e.getActionCommand();if("画直线(L)".equals(cmd)){drawCmd = "line";System.out.println("画直线的监听器启动:"+drawCmd);}else if("画椭圆(O)".equals(cmd)){drawCmd = "oval";System.out.println("画椭圆的监听器启动:"+drawCmd);}else if("画矩形(R)".equals(cmd)){drawCmd = "rectangle";System.out.println("画矩形的监听器启动:"+drawCmd);}else if("画三角形(T)".equals(cmd)){drawCmd = "triangle";System.out.println("画三角形的监听器启动:"+drawCmd);}/******************************************新建文件*****************************/else if("新建(N)".equals(cmd)){//本地功能已经实现,网络功能待完善,在此不展示}/******************************************保存文件*****************************/else if("保存(S)".equals(cmd)){//本地功能已经实现,网络功能待完善,在此不展示}/******************************************打开文件*****************************/else if("打开(O)".equals(cmd)){//本地功能已经实现,网络功能待完善,在此不展示}/******************************************退出操作*****************************/else if("退出(E)".equals(cmd)){System.out.println("退出的监听器启动");System.out.println("程序已经关闭");System.exit(0);}/******************************************关于信息*****************************/else if("关于(A)".equals(cmd)){System.out.println("关于的监听器启动");JFrame aboutFrame = new JFrame("关于\"画板\"");aboutFrame.setSize(280,240);aboutFrame.setDefaultCloseOperation(2);aboutFrame.setResizable(false);aboutFrame.setLocationRelativeTo(null);aboutFrame.setLayout(new FlowLayout());aboutFrame.setVisible(true);JLabel label = new JLabel();//创建一个超链接final JLabel la_url = new JLabel("博客:http://yacare.iteye.com");//设置链接颜色为蓝色la_url.setForeground(Color.BLUE);label.setText("<html><body>Certified by Internet Society<br>"+ "网络画板服务器端 (本大爷专属)<br>@author YangKang<br>@version 1.0<br>"+ "?Copyright 版权所有,山寨必究<br>本软件只供学习娱乐之用,严禁从事商业用途"+ "<br><br>联系作者:<br>"+ "QQ:1009425612<br>TEL:18942558998<br>"+ "Addess:保密"+ "</body></html>");aboutFrame.add(label);aboutFrame.add(la_url);//将链接添加鼠标监听器la_url.addMouseListener(new MouseAdapter() {//鼠标离开时,链接前景色变为橙色@Overridepublic void mouseExited(MouseEvent e) {la_url.setForeground(Color.ORANGE);}//鼠标进入时,链接前景色变成红色@Overridepublic void mouseEntered(MouseEvent e) {la_url.setForeground(Color.RED);}//鼠标点击超链接时,打开浏览器进入链接地址@Overridepublic void mouseClicked(MouseEvent e) {try {//定义链接地址URI uri = new URI("http://yacare.iteye.com"); Desktop dtp = Desktop.getDesktop();//是否支持此类和对象浏览if(Desktop.isDesktopSupported()&&dtp.isSupported(Desktop.Action.BROWSE)){//在浏览器中打开此链接dtp.browse(uri);}} catch (Exception e1) {e1.printStackTrace();}}});}}};/** * 网络画板通信模块,连接客户端 */private void Conn2Client() {try{//1.建立绑定在指定端口上的服务器对象 server = new ServerSocket(port);System.out.println("服务器创建成功"+this.port);//2.当有客户机连接时,等待方法就会返回,返回一个代表与客户端连接的对象while(true){//让服务器处于循环待机状态client = server.accept();//可能会发生堵塞//创建客户端的输出流ous = client.getOutputStream();dous = new DataOutputStream(ous);//创建客户端的输入流ins = client.getInputStream();dins = new DataInputStream(ins); System.out.println("Incoming"+client.getRemoteSocketAddress().toString()); //启动读取客户端数据的线程 this.start(); System.out.println("处理线程已启动,正处理登录操作!");}}catch(Exception e1){e1.printStackTrace();}}/** * 重写父类run()方法,用来读取客户端的数据 */public void run(){//在线程run中调用处理连结的方法readLineFromClient(dins);}/*** 将发送图形的代码封装到sendLine2Client方法中 * @param type 图形的类型* @param 传入两点的坐标*/public void sendLine2Client(int type,int x1,int y1,int x2,int y2){try {dous.writeByte(type); //type 表示绘制图形类型dous.writeInt(x1);dous.writeInt(y1);dous.writeInt(x2);dous.writeInt(y2);ous.flush();//强制输出System.out.println("向服务器发送直线成功");} catch (IOException e) {e.printStackTrace();}}/** *读取客户端发过来的直线信息,接收并画在窗体上 */private void readLineFromClient(DataInputStream dins) {try {while(true){type = dins.readByte();x1 = dins.readInt();y1 = dins.readInt();x2 = dins.readInt();y2 = dins.readInt();System.out.println("读取客户端发送来的图形数据成功,类型:"+type);//判断绘制图形的类型if(type == 1){ //1表示画直线//根据传入的坐标,调用绘制直线的方法来画直线g.drawLine(x1,y1,x2,y2);}else if(type == 2){//2表示画椭圆//根据传入的坐标,调用绘制椭圆的方法来画椭圆int minX = Math.min(x1, x2);int minY = Math.min(y1, y2);g.drawOval(minX,minY,Math.abs(x2-x1),Math.abs(y2-y1));}else if(type == 3){//3表示画矩形//根据传入的坐标,调用绘制矩形的方法来画矩形int minX = Math.min(x1, x2);int minY = Math.min(y1, y2);g.drawRect(minX,minY,Math.abs(x2-x1),Math.abs(y2-y1));}else if(type == 4){//4表示画三角形//根据传入的坐标,调用绘制直线的方法来画等腰三角形g.drawLine(x1,y1,x2,y2);g.drawLine(x1,y1,x1*2-x2,y2);g.drawLine(x2,y2,x1*2-x2,y2);}}} catch (IOException e) {e.printStackTrace();}finally {try {dins.close();ins.close();ous.close();dous.close();client.close();}catch (Exception e2) {e2.printStackTrace();}}}@Overridepublic void mouseClicked(MouseEvent e) {// TODO Auto-generated method stub}@Overridepublic void mousePressed(MouseEvent e) {System.out.println("鼠标监听器得到命令:"+drawCmd);//获取鼠标按下时的坐标值x1 = e.getX();y1 = e.getY();System.out.println("鼠标按下的坐标:"+"x1-->"+x1+",y1-->"+y1);}@Overridepublic void mouseReleased(MouseEvent e) {//获取鼠标释放时的坐标值x2 = e.getX();y2 = e.getY();System.out.println("鼠标松开的坐标:"+"x2-->"+x2+",y2-->"+y2);System.out.println("鼠标捕捉到的点坐标:x1-->"+x1+" y1-->"+y1+" x2-->"+x2+" y2-->"+y2);//根据命令,获取按下和释放的坐标,调用绘制直线的方法来画线/画圆if(drawCmd.equals("null")){JOptionPane.showMessageDialog(null, "请先选择绘图命令");System.out.println("未指定画图命令,请选择画图类型");System.out.println("**************************************");}if(drawCmd.equals("line")){//根据按下和释放的坐标,调用绘制直线的方法来画直线g.drawLine(x1,y1,x2,y2);//将绘图数据传到客户端type = 1;//1表示绘制图形为直线sendLine2Client(type,x1,y1,x2,y2);System.out.println("画直线成功");System.out.println("**************************************");}if(drawCmd.equals("oval")){//根据按下和释放的坐标,调用绘制椭圆的方法来画椭圆int minX = Math.min(x1, x2);int minY = Math.min(y1, y2);g.drawOval(minX,minY,Math.abs(x2-x1),Math.abs(y2-y1));//将绘图数据传到客户端type = 2;//2表示绘制图形为椭圆sendLine2Client(type,x1,y1,x2,y2);System.out.println("画椭圆成功");System.out.println("**************************************");}if(drawCmd.equals("rectangle")){//根据按下和释放的坐标,调用绘制直线的方法来画矩形g.drawLine(x1,y1,x2,y1);g.drawLine(x1,y1,x1,y2);g.drawLine(x1,y2,x2,y2);g.drawLine(x2,y1,x2,y2);//将绘图数据传到客户端type = 3;//3表示绘制图形为矩形sendLine2Client(type,x1,y1,x2,y2);System.out.println("画矩形成功");System.out.println("**************************************");}if(drawCmd.equals("triangle")){//根据按下和释放的坐标,调用绘制直线的方法来画等腰三角形g.drawLine(x1,y1,x2,y2);g.drawLine(x1,y1,x1*2-x2,y2);g.drawLine(x2,y2,x1*2-x2,y2);//将绘图数据传到客户端type = 4;//3表示绘制图形为等腰三角形sendLine2Client(type,x1,y1,x2,y2);System.out.println("画三角形成功");System.out.println("**************************************");}}@Overridepublic void mouseEntered(MouseEvent e) {// TODO Auto-generated method stub}@Overridepublic void mouseExited(MouseEvent e) {// TODO Auto-generated method stub}}
?