- 浏览: 35581 次
- 性别:
- 来自: 济南
最近访客 更多访客>>
最新评论
-
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 1088Java虚拟机是一个想象中 ... -
我常用的ubuntu软件
2008-08-15 13:44 3778聊天工具:kmess(MSN)eva(QQ)pidgin(支持 ... -
ubuntu安装中文输入法
2008-08-15 10:03 7591个人认为输入法还是安装Fcitx 的好下面就是安装过程: su ... -
ubuntu下使用QT3和QT4
2008-08-15 09:35 2191刚开始学习C++,对很多东西都不了解,由于在Ubuntu上, ... -
lunix下的java、mysql实现
2008-08-15 09:22 1132搭建java环境在Windows下是很简单的事情,可是到 ... -
ubuntu文件加密
2008-08-07 11:55 1338当Ubuntu Linux使用 ... -
ubuntu下听ape音乐
2008-08-07 11:53 4325转载于http://wolfplanet.itey ... -
linux使用经验
2008-08-07 11:49 1277转载于http://wolfplanet.iteye.com ... -
linux下的系统备份
2008-08-07 11:47 1333转载于http://wolfplanet.iteye.com ... -
怎样在ubuntu下开3D
2008-08-07 11:44 1488转载于http://wolfplanet.iteye ... -
ubuntu下的常用软件
2008-08-07 11:41 1722转载于http://wolfplanet.iteye.com ...
相关推荐
java课程设计 java实现的网络涂鸦板,支持聊天和画图
HTML5 canvas简洁涂鸦画板代码,有画图、颜色、类型、线条宽度、橡皮擦等功能,涂鸦完成可以保存为图片。
html5 canvas简洁的涂鸦画板代码 html5 canvas简洁的涂鸦画板代码
实现java聊天室,群聊和私聊,以及共享涂鸦板
HTML5 canvas多功能涂鸦画板绘图代码基于jquery-1.10.2.js制作,有直线、矩形、圆圈、铅笔、多边形 、橡皮、描边、新建 、清空、撤销、保存、剪切、复制等功能。
html5 canvas ps在线编辑涂鸦画板功能 html5 canvas ps在线编辑涂鸦画板功能
涂鸦画板小程序.zip微信小程序模板源码
简单的jQuery网页画板涂鸦代码.zip
涂鸦板 html5实现涂鸦板canvas 画布实现
一个模仿了画板涂鸦的小demo.基本的重绘实现了.实现了颜色的变化和笔记粗细的变化
html5 canvas涂鸦画板绘制图形效果
实际开发中主要用于手写签名及其它绘画涂鸦,最终生成图片,用于上传服务器。
利用绘图封装一个简单的涂鸦画板view,可以设置涂鸦线宽和颜色,撤销,清除,添加图片,保存图片
基于鸿蒙系统的多设备共享涂鸦画板,主要需要实现的功能如下: 1、涂鸦者可以选择不同的画笔,颜色进行自由涂鸦,清除画板; 2、涂鸦者也可以选择图片,进行涂鸦; 3、涂鸦者可以一键寻找附近的手机或者其他设备...
Android画板 涂鸦板 和一些相关的自定义View 画板功能包括取色 换笔形和设定粗细
这是一款功能比较简单粗暴实用的HTML5 Canvas全屏画板涂鸦代码,基本功能有选择颜色,画笔粗细,橡皮檫工具和删除撤销。电脑手机端都适合。
iOS涂鸦板可实现基本涂鸦板功能,包括更改画笔颜色,更还画笔粗细,可实现涂鸦的前进和后退,可清除涂鸦以及保存涂鸦
。NET涂鸦板源代码,让你随心所以的画图。。。
手把手带你使用Paint in 3D和Photon撸一个在线涂鸦画板.doc
HTML5 canvas绘制涂鸦画板,可选择画笔粗细、画笔颜色,有橡皮擦和清空画布功能。