最近好多天都在写通信的程序,刚开始讲时,服务器和客户端都没用到自己设计的界面,觉得很简单,服务器端有一个ServerSocket,客户端有一个Socket,简简单单的建立一个通道,后来给服务器和客户端加界面时,才发现自己并没有真正的掌握这些知识,胡哥刚讲完同步画板时,吕旭当天上午就实现了,而我觉得好高深啊,怎么实现的???虽然有些交流可总觉得自己还没入门。那两天真是不知道天天在写什么,有时听得懂被人讲的,看得懂别人的代码,就是自己不会写。。。(用某人的话说这些没有意义)
周二早上怀着惴惴不安的心情来到公司,因为没写完作业,周一休息,不会写也不怎么想写,(不会俩字很敏感)书上代码敲了一遍,敲完基本什么也没记住。。。周二上午没讲课,大神李伟给我仔仔细细分析了框架,说了大略思路,唉,觉得自己明白了,开悟了。。。
为了给设计程序一个良好的框架,胡哥给我们讲了UML作图,这个的话,如老师所说,框架很详细的话,只往框架中填代码就好了,“初中生培训三个月就可以完成”。。。可是我觉得大道至简,其实书设计思路不够熟练于是框架就变成了这样
服务器框架
客户端框架
服务器客户端界面通信
大概讲,服务器要有3个方法
ServerSocket so=new ServerSocket(port);
//读取数据 private String readString(InputStream ins) throws IOException{ //创建一个字符串缓冲区 StringBuffer stb=new StringBuffer(); char c=0; while(c!=35){ //遇到#号算一个字符串 int i=ins.read();//读取客户机发过来的一个字节 c=(char)i;//将输入的字节转换为一个char stb.append(c); } //将读到的字节转化为字符串,并调用trim去掉尾部的空格 String inputS=stb.toString().trim(); return inputS; } 区分客户端发给服务器,还是群发,加了个标志值(c) int c=ins.read(); if(c==1){//只发给服务器 String inputS=readString(ins); while(!inputS.equals("bye")){ System.out.println("客户机说"+inputS); //加到空白区域 are.setText(are.getText()+"\r\n"+inputS); inputS=readString(ins);//读取客户机下一次输入 } }else if(c==2){//发送给系统 String inputS=readString(ins); while(!inputS.equals("bye")){ System.out.println("客户机说"+inputS); //加到空白区域 are.setText(are.getText()+"\r\n"+inputS); //群发给其他客户端 StartListener.sendMsg(inputS); inputS=readString(ins);//读取客户机下一次输入 } }
//发送消息给连接我的客户端 public void sendMsg2Me(String msg){ try{ msg+="#"; out.write(msg.getBytes()); }catch(Exception ef){ ef.printStackTrace(); } }
这3个方法可能分布在不同的类中,类与类之间也因此相互连接
客户端与服务器端相对应,方法也相对应
Socket client=new Socket("IP",port);
public void Connect(){ try{ ous=so.getOutputStream();//获取输出流 System.out.println("服务器连接成功!"); while(true){ //读取服务器发来的消息 ins=so.getInputStream();//获取输入流 String message=""; int b = ins.read(); while(b!=35){ //#号结尾 message +=(char)b; b = ins.read(); } //显示在客户端的area上 are.setText(are.getText()+"\r\n"+message); System.out.println("服务器传过来的是="+message); } }catch(Exception e){ e.printStackTrace(); } }
//发送消息 public void sendMsg(String s){ byte [] by=s.getBytes(); try { ous.write(by); } catch (Exception e) { e.printStackTrace(); } }
最后效果
1.客户端发给服务器
2.客户端群发
3.一行代码解决汉字乱码
//读取汉字
message=new String(message.getBytes("ISO-8859-1"),"GB2312");
其实关于服务器与客户端的读写,在做同步画板时更能深刻体现,一边写进去什么dou.writeInt(),另一边就即读取什么dis.readInt();
x2=e.getX(); y2=e.getY(); if(s.equals("画线")){ g.drawLine(x1, y1, x2, y2); try{ dos.writeInt(1); dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(x2); dos.writeInt(y2); System.out.println("x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2); }catch(Exception e1){ e1.printStackTrace(); } }else if(s.equals("画圆")){ int r1=Math.abs(x2-x1); int r2=Math.abs(y2-y1); g.drawOval(x1, y1, r1, r2); try{ dos.writeInt(2); dos.writeInt(x1); dos.writeInt(y1); dos.writeInt(r1); dos.writeInt(r2); System.out.println("x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2); }catch(Exception e1){ e1.printStackTrace(); } }else if(s.equals("画图")){ ImageIcon con=new ImageIcon("images/psb.jpg"); //缓冲图纸,实为窗体性质 image01=new BufferedImage(con.getIconWidth(),con.getIconHeight(),BufferedImage.TYPE_INT_RGB); Graphics g2=image01.getGraphics(); g2.drawImage(con.getImage(), 0, 0, null); //白纸划到窗体上 g.drawImage(image01, 0, 0, null); try{ int width=image01.getWidth(); int height=image01.getHeight(); dos.writeInt(3); dos.writeInt(width); dos.writeInt(height); //把每个像素点的颜色写进去 for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ dos.writeInt(image01.getRGB(i, j)); } } }catch(Exception e1){ e1.printStackTrace(); } }
//读出数据的方法 public void readMsg(InputStream ins){ try { while(true){ DataInputStream dis=new DataInputStream(ins); int type=dis.readInt(); if(1==type){ //读取客户端画线的数据 int x1=dis.readInt(); int y1=dis.readInt(); int x2=dis.readInt(); int y2=dis.readInt(); System.out.println("x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2); g.drawLine(x1,y1,x2,y2); }else if(2==type){ //读取客户端画圆的数据 int x1=dis.readInt(); int y1=dis.readInt(); int r1=dis.readInt(); int r2=dis.readInt(); g.drawOval(x1, y1, r1, r2); }else if(3==type){ //读取客户端画图的数据 int width=dis.readInt(); int height=dis.readInt(); for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ g.setColor(new Color(dis.readInt())); g.drawLine(i, j, i, j); } } } } } catch (Exception e) { e.printStackTrace(); }
最终同步画板的效果
在写客户端时用了鼠标监听器和事件监听器都为内部类,内部类最大的好处是基本上省略了传参过程,节省很多代码,最大的缺点是不清晰,在编程语言类往往讲究清晰第一,在写服务器端是鼠标监听器和时间监听器均是外部类,尝试了一下,过程中出现过空指针,但都不是什么大问题,容易解决。在写的过程中还犯了个错误,用了static的一个getter方法,导致同步时服务器只能同步客户端的一条线,原因是第二个调用getter方法覆盖了前一次的数据,static用时需谨慎和思路很清晰啊。。。。。
相关推荐
Java Socket通信小结 在Java编程中,Socket通信是一种基于TCP/IP协议的网络通信方式,它允许两个应用程序之间建立可靠的、双向的数据传输连接。本文将深入探讨Java Socket通信的基础知识,以及如何通过Java实现一个...
【CP1H变频器通信小结】 本文主要围绕CP1H变频器与Modbus-RTU通信的配置和特点进行阐述。CP1H变频器是三菱电机推出的一款可编程控制器,它具备串口通信功能,可以与其他设备通过Modbus-RTU协议进行数据交换。 **...
在Linux环境下进行Qt应用程序开发时,串口通信是一项常见的需求。Qt本身虽然没有提供专门的串口通信类,但可以通过QIODevice抽象层与其他系统接口进行交互。本文将总结作者在Linux下使用Qt进行串口通信的经验,探讨...
进程间的通信(IPC,Inter-Process Communication)是操作系统中一种重要的功能,允许不同进程之间交换信息,协同工作。本文将重点讨论其中的共享内存方式。 共享内存是一种高效的数据交换机制,它允许多个进程共享...
"通信实训小结" 通信实训小结是指在通信领域中的实习或实践活动,本文档记录了某个实习生的两周实习经历,包括了实习的内容、收获的知识、以及未来努力的方向。 一、通信实训内容 通信实训的内容涵盖了多个方面,...
#### 4 “IEC61850ServerLibrary“软件包通信小结 通过以上步骤,我们可以成功地将SIMATIC S7-300 PLC配置为IEC61850服务器,并通过“IEC61850ServerLibrary”软件包实现了与基于IEC61850标准的其他设备之间的通信...
通信广场营业员精编工作小结.rar
《通信专业实务:传输与接入》是一本针对全国通信专业技术人员职业水平考试的教程,它涵盖了有线和无线传输与接入的重要技术。该书旨在帮助考生掌握通信领域的核心概念和实际应用。 首先,书中详细讲解了有线传输与...
### Delphi Socket 通信编程要点小结 #### 一、引言 在现代通信系统开发过程中,基于Delphi的Socket编程技术因其高效性与灵活性而备受青睐。本文将结合实践经验,对Delphi环境下进行Socket通信时所遇到的关键问题...
标题中的“通信广场营业员精编工作小结”暗示了这份文档主要涵盖了通信广场营业员的工作总结和经验分享,这通常涉及到与客户服务、销售技巧、业务处理效率以及个人职业素养等相关的内容。描述中提到的“展示企业形象...
现代通信技术报告,关于程控交换机和移动通信切换
本章知识点小结 第二章 信道与噪声 2.1 信道的基本概念 2.2 恒参信道及其对所传信 号的影响 2.3 随参信道及其对所传信 号的影响 2.4 信道的加性噪声 2.5 通信中的常见噪声 2.6 信道...
【通信广场营业员职责与挑战】 作为一名通信广场的营业员,我深知自己的职责不仅仅是销售通信产品和服务,更是代表企业形象,展现"移动人"的专业素养和热情态度。我们的工作是与客户面对面交流的"窗口",是连接企业...
本次实验是关于操作系统中的进程通信,主要涉及了进程的创建、控制、以及多种通信方式,包括信号通信和管道通信。通过实验,目的是加深对进程概念的理解,掌握并发执行的本质,并学习如何解决进程间的互斥问题。实验...
介绍移动通信原理,供广大通信专业人员学习
第二代移动通信系统 --- 2G:数字系统 基本特征:数字技术、数字处理电路SIM卡,手机体积小质量轻、 大容量,TDMA/FDD, CDMA/FDD; 主流标准:GSM,NADC(IS-136),PDC(TDMA); IS-95(CDMA) ; 第三代移动通信系统 -...