- 浏览: 36192 次
- 性别:
- 来自: 济南
最近访客 更多访客>>
最新评论
-
guooscar:
现在的大学怎么就不与时俱进一点呢,都2009年了还在用1987 ...
用c开发的游戏 -
daiming253685:
这怎么读得懂啊
用c开发的游戏 -
zhangzuohai:
请问这是在那个编译器下编译的呀,cv or bc or oth ...
用c开发的游戏 -
xiehao315:
我不会用C,提个建议,能不能多几行注释呀!
因为现在没有谁会认 ...
用c开发的游戏 -
shzhlo:
太多错误了,能不能调好了,再放上来
用c开发的游戏
这是我自己写的一个C/S架构的类似MSN的聊天工具,当然功能和稳定性都差远了。下面就直入正题(由于篇幅过长,所以分两篇)
一、功能
多人在线绘图,即时显示,群聊,私聊,在线隐身转换,点歌,更改本地字体,剪切复制等很基本的功能,但都不是很完善。有兴趣的朋友可以看一下,对照这些功能可以再完善一下。
二、主要代码介绍
主要部分是ServerThread.java,ServerStartWindow.java,ClientThread.java,ClientFrame.其中ServerThread.java是服务器端用来处理多用户请求的一个线程,而ServerStartWindow.java负责连接这些线程。ClientThread.java是客户端的一个线程,负责接收服务器传来的信息,ClientFrame是客户端的界面,同时还肩负着向服务器发送信息的任务。下面我着重介绍一下这几个类。
ServerThread.java
先看一下构造函数
public ServerThread(Socket s, Vector<ServerThread> v) { this.socket = s; this.threads = v; try { oos = new ObjectOutputStream(socket.getOutputStream()); ois = new ObjectInputStream(socket.getInputStream()); new Thread(new Runnable() { public void run() { boolean first=true; while (true) { try { write(checkDatabase.getOnlineUser()); if(first){ Thread.sleep(1000); first=false; }else{ Thread.sleep(5000); } } catch (Exception e) { } } } }).start(); } catch (IOException e) { e.printStackTrace(); } }
这个构造函数并没什么特别,就是获得一个连接客户端的Socket,并且得到一个Vector<ServerThread>,这个向量存储的是连接的服务器的所有线程。而那个run()主要是为了实时更新在线用户列表,我想不出别的办法就用了这。
然后是这个线程类最重要的run方法
public void run() { Object o = this.read(); //从客户端读入对象 String flag = (String) o; //强转为String,flag是用来判断客户端这次操作主要目的是登录还是注册 if (flag.substring(0, 4).equals("name")) { //用户登录 sname = flag.substring(4); this.write(this.currentImage); System.out.println("have write currentImage"); //像这种System.out.println的都是调试程序用的 o = null; while (true) { o = this.read(); System.out.println("have read"); if (o == null) { System.out.println("read null"); } if (o instanceof String) { String msg = (String) o; if (msg.trim().equals("quit")) { checkDatabase.setUserOffline(sname); for (int i = 0; i < threads.size(); i++) { ServerThread st1 = threads.elementAt(i); st1.write("**********************" + sname + " leave ***********************\n"); st1.write(checkDatabase.getOnlineUser()); //write()方法是用来向客户端写入的 System.out.println("quit"); } threads.remove(this); //从线程向量中移除这个线程 break; } else if (msg.equals("iwanthide")) { //用户想隐身 checkDatabase.setUserOffline(sname); for (int i = 0; i < threads.size(); i++) { ServerThread st1 = threads.elementAt(i); st1.write(checkDatabase.getOnlineUser()); } } else if (msg.equals("iwantshow")) { checkDatabase.setUserOnline(sname); } else if (msg.equals("iwantcheck")) { //用户想要检索数据库的数据 System.out.println("have receiver check message...."); String[] checkMess = {"checkmessage", checkDatabase.getMessage(this.getName())}; this.write(checkMess); System.out.println("hafve writer check mess"); } else if (msg.length() >= 7) { if (msg.substring(0, 7).equals("private")) { String requestName = msg.substring(7); for (int k = 0; k < threads.size(); k++) { ServerThread str = threads.elementAt(k); if (str.getName().equals(requestName)) { String[] sRe = {"request", this.getName()}; str.write(sRe); break; } } }else if(msg.substring(0,9).equals("sendMusic")){ String musicName=msg.substring(9,14); System.out.println(musicName); String sendName=msg.substring(14); String[] music={"sendMusic",musicName}; for(int i=0;i<threads.size();i++){ ServerThread stt=threads.elementAt(i); if(stt.getName().equals(sendName)){ stt.write(music); break; } } } else if (msg.substring(0, 9).equals("iwantsave")) { checkDatabase.saveMessage(FormatDate.nowDate() + " ×××× " + msg.substring(9), this.getName()); this.write("successsave"); } else { for (int i = 0; i < threads.size(); i++) { ServerThread st1 = threads.elementAt(i); st1.write(sname + " " + (String) o); } } } else { for (int i = 0; i < threads.size(); i++) { ServerThread st1 = threads.elementAt(i); st1.write(sname + " " + (String) o); } } } else if (o instanceof ImageIcon) { //如果传入的是ImageIcon证明是涂鸦板图像 this.currentImage=(ImageIcon)o; for (int i = 0; i < threads.size(); i++) { ServerThread st1 = threads.elementAt(i); if (i == this.getID()) { continue; } st1.write(o); } } else if (o instanceof String[]) { //String[]数组是为了方便判断客户端私聊问题的 String[] msg = (String[]) o; if (msg[0].equals("iaccept")) { //证明一个客户接受了另一个客户的私聊请求 System.out.println("have accept"); String acceptName = msg[1]; for (int k = 0; k < threads.size(); k++) { ServerThread str = threads.elementAt(k); if (str.getName().equals(acceptName)) { InetAddress ipAddress = this.socket.getInetAddress(); str.write(ipAddress); //这是获取一个客户的IP,并发给另一个客户,这样在他们之间便可以以这个IP建立私聊Socket break; } } } else if (msg[0].equals("ideny")) { String denyName = msg[1]; for (int k = 0; k < threads.size(); k++) { ServerThread str = threads.elementAt(k); if (str.getName().equals(denyName)) { str.write("deny"); break; } } } } } } else if (flag.equals("register")) { //这个条件证明用户是要注册 sname = ""; while (true) { o = this.read(); String[] registMsg = (String[]) o; String msg = registMsg[0];//得到从登录端得到的信�? if (msg.equals("enter")) { String userName = registMsg[1]; String userPassword = registMsg[2]; boolean correct = checkDatabase.checkUserInUsers(userName, userPassword); if (correct) { this.write("entersuccess"); } else { this.write("passwordwrong"); } } else if (msg.equals("regist")) { String userName = registMsg[1]; String userPassword = registMsg[2]; boolean success = checkDatabase.insertIntoUsers(userName, userPassword); if (success) { this.write("registsuccess"); } else { this.write("usernameexist"); } } } } threads.remove(this); try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
我写的很长,主要是这是整个系统的关键所在,就是这个线程负责整体的协调调度。开始先读入一个对象Object(由于不知道客户端会发来什么信息),后面就是对这些信息分类并分别处理。具体作用已在注释里写的很清楚了。
ServerStartWindow.java
主要代码
static void showFrame() { String msg = ""; ServerFrame sf = new ServerFrame(); //一个简单的服务器窗口,没什么实际作用 sf.setVisible(true);//关闭窗口时退出程序 ServerSocket socket = null; Vector<ServerThread> threads = new Vector<ServerThread>(); //这就是ServerThread.java中用到的向量 msg += "listen\n"; sf.jTextPaneServerMessage.setText(msg); try { socket = new ServerSocket(8888); } catch (Exception e) { msg += "server failed....\n"; sf.jTextPaneServerMessage.setText(msg); return; } CheckDatabase checkDatabase=new CheckDatabase(); sf.setJList(checkDatabase.getAllUser()); try { int ID = 0; while (true) { Socket s = socket.accept(); msg += "accepted\n"; sf.jTextPaneServerMessage.setText(msg); ServerThread st = new ServerThread(s, threads); st.setID(ID++); threads.addElement(st); new Thread(st).start(); msg += "listen again....\n"; sf.jTextPaneServerMessage.setText(msg); } } catch (Exception e) { e.printStackTrace(); } }
这段代码的作用就是不断的监听客户端的请求,每当有一个客户连接时,就为他新建一个ServerThread,并将其添加到向量中。
好了,服务器端的代码主要就这些了,另外还有连接数据库的。本人属于刚入门级的,所以写的代码很烂,但还是把代码发上来供大家批评指正。我还是喜欢开源啊!
下面介绍客户端较重要的两个类
ClientThread.java
先看一下它的构造函数
public ClientThread(ObjectInputStream ois,ClientFrame cf){ this.ois=ois; this.cf=cf; }
其中的ois参数是负责接收服务器端发来的信息的,而cf是客户端另一个重要类。很简单。下面是run方法
public void run(){ String s = ""; try { while (true) { Object o = cf.read(); Thread tt; if (o instanceof String) { String msg = (String) o; if (msg.equals("deny")) { //私聊惨遭拒绝 JOptionPane.showMessageDialog(cf, "you have been denied"); } else if (msg.equals("successsave")) { JOptionPane.showMessageDialog(cf, "you have successfully save your message"); } else { s += (String) o + "\n"; cf.jTextPaneChatArea.setText(s); } } else if (o instanceof javax.swing.ImageIcon) { //如果是收到的图像,则画在绘图板上 javax.swing.ImageIcon i = (javax.swing.ImageIcon) o; Image image = i.getImage(); ToolkitImage ti = (ToolkitImage) image; cf.drawComponent.drawPanel.setImage(ti.getBufferedImage()); cf.repaint(); } else if (o instanceof Vector) { //在线用户列表 cf.setJList((Vector) (o)); } else if (o instanceof InetAddress) { // 这里是接受IP地址,然后与其连接建立私聊通道 final Object oo = o; tt = new Thread(new Runnable() { public void run() { PrivateClient pr = new PrivateClient((InetAddress) oo); } }); tt.start(); } else if (o instanceof String[]) { //这是有人来请求与自己私聊 String[] msg = (String[]) o; if (msg[0].equals("request")) { PrivateDialog pd = new PrivateDialog(msg[1], cf); if (pd.getAccept()) { String[] sent = {"iaccept", msg[1]}; cf.write(sent); final String nameOfClient = msg[1]; tt = new Thread(new Runnable() { public void run() { PrivateServer pr = new PrivateServer(nameOfClient, cf.getMyName()); } }); tt.start(); } }else if(msg[0].equals("sendMusic")){ URL file1 = getClass().getResource(msg[1]); this.cf.audioClip=java.applet.Applet.newAudioClip(file1); JOptionPane.showMessageDialog(this.cf,"some one have pick you a music,enjoy it!"); } else if (msg[0].equals("checkmessage")) { String sMess = cf.jTextPaneChatArea.getText() + "****这是你上次的聊天记录****\n" + msg[1] + "\n****聊天记录结束****\n"; cf.jTextPaneChatArea.setText(sMess); } else { String[] sent = {"ideny", msg[1]}; cf.write(sent); } } } } catch (Exception e) { s += "Error"; cf.jTextPaneChatArea.setText(s); } }
这段代码也很简单,其实就是接受信息然后分类处理。
ClientFrame.java
这是客户端的界面,同时也负责很多业务,所以是最大的一个类,下面看一下主要代码
public void actionPerformed(ActionEvent e) { if (e.getSource() == this.jButtonSent) { s = "speak to " + this.sendTo + ": " + this.jTextPaneUser.getText() + " <<<<<<<<<<<<<<<<<<<<<" + FormatDate.nowDate(); t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } else if (e.getSource() == this.buttonFont) { FontDialog fd = new FontDialog(this.jTextPaneChatArea.getFont(), this); fd.setVisible(true); this.jTextPaneChatArea.setFont(fd.getChoosedFont()); this.jTextPaneUser.setFont(fd.getChoosedFont()); } else if (e.getSource() == this.buttonPrivate) { this.sendTo = (String) (this.jListUserList.getSelectedValue()); if (this.sendTo == null) { JOptionPane.showMessageDialog(this, "no person is selected"); } else if (this.sendTo.equals("ALLPERSON")) { JOptionPane.showMessageDialog(this, "you cannot private chat with allperson"); } else { s = "private" + this.jListUserList.getSelectedValue(); t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } } else if (e.getActionCommand().equals("hide")) { s = "iwanthide"; this.buttonHideShow.setLabel("show"); t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } else if (e.getActionCommand().equals("show")) { s = "iwantshow"; this.buttonHideShow.setLabel("hide"); t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } else if (e.getSource() == this.buttonCheck) { s = "iwantcheck"; t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } else if (e.getSource() == this.buttonSave) { s = "iwantsave" + this.jTextPaneChatArea.getText(); t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } else if (e.getSource() == this.buttonSaveLocal) { if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { final String fileName = fileChooser.getSelectedFile().getAbsolutePath(); Thread tt = new Thread(new Runnable() { public void run() { try { PrintWriter pw = new PrintWriter(new FileOutputStream(fileName)); pw.write(jTextPaneChatArea.getText()); pw.close(); JOptionPane.showMessageDialog(ClientFrame.this, "you have successfully save your message to local file"); } catch (Exception e) { e.printStackTrace(); } } }); tt.start(); try { Thread.sleep(300); tt.stop(); } catch (Exception ex) { } } } else if (e.getSource() == this.buttonListenMusic) { if (this.audioClip == null) { JOptionPane.showMessageDialog(this, "util now you haven't receive music"); } else { if (this.firstAudio) { audioThread.start(); this.firstAudio = false; } else { try { audioThread.stop(); Thread.sleep(100); audioThread = new Thread(new Runnable() { public void run() { new AudioPlayDialog(audioClip); } }); audioThread.start(); } catch (Exception et) { et.printStackTrace(); } } } } else if (e.getSource() == this.buttonSendMusic) { String name = (String) this.jListUserList.getSelectedValue(); if (name == null) { JOptionPane.showMessageDialog(this, "you haven't choosen any person!"); } else { ChooseMusicDialog mDialog = new ChooseMusicDialog(this); String music = mDialog.getMusic(); if (music == null) { } else { s = "sendMusic" + music + name; t = new Thread(this.runnable); t.start(); try { Thread.sleep(300); t.stop(); } catch (Exception ex) { } } } } }
上面就是能干点事的代码,很简单的处理事件,然后发送信息给ServerThread。
好了,到这主要部分就说完了。只是今天有点失眠,就写了篇文章,把之前做过的一个小东西拿出来献丑了,有很多的bug。还望高手指点啊。附件是我的源码,没经过优化,有点乱。用netbeans6.0以上版本可以成功导入,以下版本会出现乱码。
转载于wolfplanet.iteye.com
发表评论
-
Java虚拟机应用
2008-08-19 16:19 1118Java虚拟机是一个想象中 ... -
我常用的ubuntu软件
2008-08-15 13:44 3812聊天工具:kmess(MSN)eva(QQ)pidgin(支持 ... -
ubuntu安装中文输入法
2008-08-15 10:03 7638个人认为输入法还是安装Fcitx 的好下面就是安装过程: su ... -
ubuntu下使用QT3和QT4
2008-08-15 09:35 2228刚开始学习C++,对很多东西都不了解,由于在Ubuntu上, ... -
lunix下的java、mysql实现
2008-08-15 09:22 1161搭建java环境在Windows下是很简单的事情,可是到 ... -
ubuntu文件加密
2008-08-07 11:55 1371当Ubuntu Linux使用 ... -
ubuntu下听ape音乐
2008-08-07 11:53 4360转载于http://wolfplanet.itey ... -
linux使用经验
2008-08-07 11:49 1308转载于http://wolfplanet.iteye.com ... -
linux下的系统备份
2008-08-07 11:47 1369转载于http://wolfplanet.iteye.com ... -
怎样在ubuntu下开3D
2008-08-07 11:44 1520转载于http://wolfplanet.iteye ... -
ubuntu下的常用软件
2008-08-07 11:41 1750转载于http://wolfplanet.iteye.com ...
相关推荐
【标题】:“java实现的网络涂鸦板程序,支持聊天和画图” 这个项目是一个基于Java编程语言开发的网络应用程序,旨在提供一个在线的、互动的涂鸦平台,用户可以在同一时间进行聊天和画图。它结合了实时通信与图形...
涂鸦聊天室是一款基于Java技术实现的在线互动平台,它允许用户通过文字交流的同时,能够进行实时的涂鸦分享,增强了聊天的趣味性和互动性。在这个应用中,我们可以看到Java的强大功能以及在网络通信和图形处理方面的...
描述中的"实现java聊天室,群聊和私聊,以及共享涂鸦板"进一步确认了该程序的功能,不仅包括基本的文字聊天,还具备了多人互动的涂鸦功能。 在Java中,开发聊天室应用通常涉及到以下几个关键知识点: 1. **网络...
涂鸦画板小程序是一款基于微信小程序开发的模板应用,它为用户提供了一个自由创作、涂鸦的平台。这个项目源码的发布,对于开发者而言,是一个极好的学习和参考资源,可以深入了解微信小程序的开发流程和相关技术。 ...
这个"HTML5 canvas简洁涂鸦画板代码.zip"提供的就是一个基于canvas实现的简单涂鸦画板,拥有丰富的功能,如画图、选择颜色、切换线条类型、调整线条宽度以及使用橡皮擦等。下面我们将详细探讨这些知识点。 首先,...
在这个涂鸦画板中,可能有一个特定的div元素作为画布,jQuery可以方便地选中这个元素并为其添加必要的样式和属性,如设置宽高、背景色等。 2. **事件处理**:jQuery的事件处理功能使得在画板上监听鼠标移动、点击等...
这个“html5 canvas ps在线编辑涂鸦画板功能”是基于Canvas技术实现的一个互动性强、功能丰富的画板应用,可以模拟Photoshop的部分功能,让用户在浏览器上进行绘画和图像编辑。 首先,Canvas通过JavaScript API提供...
这个"HTML5 canvas多功能涂鸦画板绘图代码"项目利用了canvas和jQuery库来实现一个功能丰富的在线绘图应用程序。以下是关于这个项目的详细知识点: 1. **HTML5 Canvas**:Canvas是一个HTML5标签,它提供了一个二维...
总之,"swift-ZWGraphicView签名涂鸦画板"是一个实现手绘签名和涂鸦功能的Swift项目,它涉及了手势识别、图形绘制、用户交互、图像处理以及网络通信等多个iOS开发的关键知识点。通过这个项目,开发者可以深入理解...
在这个"html5 canvas简洁的涂鸦画板代码"示例中,我们将深入探讨如何利用HTML5 Canvas实现一个基本的涂鸦画板功能。 首先,Canvas元素是HTML5新增的一个特性,它通过JavaScript来控制图形的绘制。在HTML文档中,...
在这个涂鸦画板中,jQuery可能用于简化DOM操作,如监听用户交互、触发动画效果以及与服务器的异步通信。 5. **本地存储**:HTML5引入了Web Storage API,包括`localStorage`和`sessionStorage`,用于在用户的浏览器...
此外,重绘功能是实现涂鸦画板的关键。每当用户在画布上移动鼠标时,程序都需要捕获鼠标位置,计算出新的线条,并将这些线条绘制到画布上。在鼠标按下和释放期间,这通常涉及到`mousedown`、`mousemove`和`mouseup`...
3. **涂鸦画板实现**: - **事件监听**:首先,我们需要监听用户的鼠标或触屏事件,如`mousedown`(鼠标按下)、`mousemove`(鼠标移动)和`mouseup`(鼠标抬起)。当用户开始绘画时,记录下起点坐标;在移动过程中...
本项目名为"jQuery+CSS3实现在线编辑涂鸦画板功能",它结合了HTML5的强大特性,提供了用户可以自由涂鸦、调节颜色以及应用高斯模糊效果的功能。这个功能的实现对于在线教育、设计协作或者娱乐类网站来说都是一个极其...
这个"HTML5 canvas绘制涂鸦画板.zip"压缩包包含了一个基于HTML5 canvas技术实现的简易涂鸦画板应用。这个应用允许用户在网页上自由地绘画,拥有选择画笔粗细、画笔颜色、橡皮擦以及清空画布的功能,极大地提升了用户...
3. **创建在线涂鸦画板**: 要创建一个在线涂鸦画板,首先需要一个Unity 3D项目,并引入Paint in 3D和Photon Unity Networking 2插件。接着,创建一个平面(Quad)作为画板,并添加P3dPaintable、P3dMaterialCloner和...
下面我们将深入探讨这个项目的知识点,并展示如何利用这些源代码来实现一个功能齐全的涂鸦板。 首先,我们需要理解。NET框架的基础知识。。NET是由微软公司推出的开发平台,它提供了丰富的类库和开发工具,支持多种...
`css`目录中的CSS文件则负责样式设计,包括布局、按钮样式、颜色选择器等,使得涂鸦画板在不同设备上都能有良好的显示效果。例如,可能会设置Canvas的边框、按钮的尺寸和位置等。 总结来说,HTML5 Canvas全屏画板...
涂鸦板是网页交互设计中常见的一种功能,它允许用户在网页上自由绘画,常用于在线教育、互动娱乐和创意设计等领域。HTML5是现代网页开发的重要标准,其中Canvas元素为实现涂鸦板提供了可能。Canvas是一个基于矢量...
1. **源代码**:压缩包中的涂鸦画板小程序源代码,包括JavaScript、WXML和WXSS文件,是理解小程序运行机制和进行二次开发的基础。 2. **设计素材**:可能包含图标、背景图片等设计元素,可用于自定义用户界面。 3. *...