做一个PC聊天工具(一)
2015-08-04 10:45
183 查看
想要定制一个自己的聊天工具,然后进行群聊。
我们可以先尝试让客户机和服务器沟通
Step1.构建服务器
第一步是做一个服务器出来。
JAVA中由ServerSocket这个套接字创建服务器(Socket是创建客户机用的)
有了服务器当然也要有客户机,紧接着要有客户机
怎么写?Socket client = new Socket(); ?
当然不是这样写了,服务器是等待客户机的连接,我们只要得到连接的客户机就行了,而不需要自己创建一个客户机
我们还可以通过client.getRemoteSocketAddress()获得客户机的地址,将它输出来,以提示客户机已经连接到服务器上了。
之后就是服务器与客户机之间的对话了,我们可以用一个类专门处理这个内容。
Step2.服务器与客户机对话
细节不说了,直接上代码,创建一个Message类来处理对话。
3、进行沟通
电脑的端口可以充当客户机,只要电脑开启了telnet功能就可以,在控制面板中开启,具体怎么开启就不细说了。
打开电脑的命令提示符,输入telnet localhost port(port是程序中实际写入的端口号)比如程序中是65535,则在命令提示符中输入的则是telnet localhost 65535。
如果连接成功就会在命令提示符中看到服务器发给客户机的欢迎消息(欢迎XXX登录服务器),这就实现了从服务器发消息到客户机的过程。
如果在命令提示符中输入消息并回车,在eclipse的控制台中也会看到该消息显示出来,这就完成了从客户机到服务器的过程。
但是你会发现发完一条消息之后就没有然后了,连接就中断了…
这是因为我们服务器读完一条来着客户机的消息之后就把is os给关闭了,服务器和客户机之间的连接自然就中断了。其实修改的方法很简单,让readMsg一直循环执行就可以了,就像下面这样:
已经实现单个客户机和服务器的连接和通信了,下一步就是要让多个客户机连接服务器,这就要用到多线程。
把核心代码晒出来看看:
所有与服务器连接的客户机都放到vector中去(考虑到客户机之间没有什么顺序关系,所以采用Vector这个容器去容纳客户机)
因为要实现群聊而不是服务器和客户机通信,所以新定义一个类去实现这个功能,也就是chatMessage类。
chatMessage应是一个继承自Thread的类,每一个客户机与服务器的连接都是一个线程,这个类中要处理的操作是,读取客户机发来的消息,并群发给其他的客户机。
所以它需要的参数是 client 与容纳所有客户机的 vector。
基本的方法是readMsg 和writeMsg。
下面是chatMessage的代码:
在电脑的命令提示符中就可以模拟这么一个群发的过程,但是这样没有实际的服务器或者客户机的UI,我们下一步就是创建他们的UI。
我们可以先尝试让客户机和服务器沟通
Step1.构建服务器
第一步是做一个服务器出来。
JAVA中由ServerSocket这个套接字创建服务器(Socket是创建客户机用的)
/* * @param port:端口号(0~65535中不被占用的端口即可) */ ServerSocket server = new ServerSocket(port);
有了服务器当然也要有客户机,紧接着要有客户机
怎么写?Socket client = new Socket(); ?
当然不是这样写了,服务器是等待客户机的连接,我们只要得到连接的客户机就行了,而不需要自己创建一个客户机
Socket client = server.accept() System.out.println("连接客户机"+client.getRemoteSocketAddress());//输出客户机的地址
我们还可以通过client.getRemoteSocketAddress()获得客户机的地址,将它输出来,以提示客户机已经连接到服务器上了。
之后就是服务器与客户机之间的对话了,我们可以用一个类专门处理这个内容。
Step2.服务器与客户机对话
细节不说了,直接上代码,创建一个Message类来处理对话。
package ch0802; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class Message { public void information(Socket client) throws IOException{ //Step1.定义输入输出流(输入: 输出:) InputStream is = client.getInputStream(); OutputStream os = client.getOutputStream(); //Step2.获取到客户机的端口号 String remoteAddress = client.getRemoteSocketAddress().toString(); String client_port = remoteAddress.substring(remoteAddress.lastIndexOf(":"),remoteAddress.length()); //Step3.服务器发信息给客户机让服务器发一条消息给客户机 注意:对于Android 则为getBytes("utf-8") writeMsg(os,("欢迎"+client_port+"登陆服务器\r\n")); String strb = readMsg(is); System.out.println(strb.toString()); is.close(); os.close(); } public void writeMsg(OutputStream os,String msg) throws IOException{ os.write(msg.getBytes()); } public String readMsg(InputStream is) throws IOException{ int b; StringBuffer strb = new StringBuffer(); //服务器读取客户机发送过来的消息,换行表示结束 while((b=is.read())!=13){ char c = (char)b; strb.append(c); } return strb.toString(); } }
3、进行沟通
电脑的端口可以充当客户机,只要电脑开启了telnet功能就可以,在控制面板中开启,具体怎么开启就不细说了。
打开电脑的命令提示符,输入telnet localhost port(port是程序中实际写入的端口号)比如程序中是65535,则在命令提示符中输入的则是telnet localhost 65535。
如果连接成功就会在命令提示符中看到服务器发给客户机的欢迎消息(欢迎XXX登录服务器),这就实现了从服务器发消息到客户机的过程。
如果在命令提示符中输入消息并回车,在eclipse的控制台中也会看到该消息显示出来,这就完成了从客户机到服务器的过程。
但是你会发现发完一条消息之后就没有然后了,连接就中断了…
这是因为我们服务器读完一条来着客户机的消息之后就把is os给关闭了,服务器和客户机之间的连接自然就中断了。其实修改的方法很简单,让readMsg一直循环执行就可以了,就像下面这样:
while(true){ String strb = readMsg(is); System.out.println(strb.toString()); }
已经实现单个客户机和服务器的连接和通信了,下一步就是要让多个客户机连接服务器,这就要用到多线程。
把核心代码晒出来看看:
while(true){ //等待客户机的连接,如果有客户机连接上来就返回客户机的Socket对象,如果没有则让服务器一直处于等待状态 Socket client = server.accept(); //开启一个线程,让线程负责对该客户机的所有消息做处理操作 ChatMessage cm = new ChatMessage(client,vector); //启动线程 cm.start(); vector.add(cm); }
所有与服务器连接的客户机都放到vector中去(考虑到客户机之间没有什么顺序关系,所以采用Vector这个容器去容纳客户机)
因为要实现群聊而不是服务器和客户机通信,所以新定义一个类去实现这个功能,也就是chatMessage类。
chatMessage应是一个继承自Thread的类,每一个客户机与服务器的连接都是一个线程,这个类中要处理的操作是,读取客户机发来的消息,并群发给其他的客户机。
所以它需要的参数是 client 与容纳所有客户机的 vector。
基本的方法是readMsg 和writeMsg。
下面是chatMessage的代码:
package ch0803; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Vector; public class ChatMessage extends Thread{ //实现群聊 Vector<ChatMessage> vector; Socket client; InputStream is; //客户机的输入流 OutputStream os; //客户机的输出流 //构造函数 public ChatMessage(Vector<ChatMessage> vector,Socket client){ try { this.client = client; this.vector = vector; is = client.getInputStream(); os = client.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } } public void run(){ //Step1.输出欢迎登录 String msg = "欢迎客户机"+this.getId()+"连接服务器"; //getId获得的是线程号 writeMsg(msg); //Step2.循环与客户机连接,接收客户机发来的消息 while(true){ msg = readMsg(); if(msg!="bye"){ //将消息群发至其他的客户机 msg = this.getId()+"说:"+msg+"\r\n"; for(int i=0;i<vector.size();i++){ ChatMessage cm = vector.get(i); cm.writeMsg(msg); } }else{ //将消息群发至其他的客户机 msg = this.getId()+"说:"+msg+"\r\n"; for(int i=0;i<vector.size();i++){ ChatMessage cm = vector.get(i); cm.writeMsg(msg); } break; //结束连接 } } } public boolean writeMsg(String msg){ boolean flag=false; try { os.write(msg.getBytes()); flag = true; } catch (IOException e) { e.printStackTrace(); } return flag; } public String readMsg(){ StringBuffer msg = new StringBuffer(); int i; try { while((i=is.read())!=13){ msg.append((char)i); } } catch (IOException e) { e.printStackTrace(); } return msg.toString(); } }
在电脑的命令提示符中就可以模拟这么一个群发的过程,但是这样没有实际的服务器或者客户机的UI,我们下一步就是创建他们的UI。
相关文章推荐
- 1000多块整个插板,arduino + android 蓝牙插板的实现--屌丝版
- dSploitzANTI渗透教程之启动zANTI工具
- Dairy
- 经典之希尔排序
- HDOJ 1800 Flying to the Mars(LIS)
- 数据结构 树状数组
- C/C++中const关键字详解
- hdu1671 trie树
- 产品经理修炼随笔
- 『Spring.NET+NHibernate+泛型』框架搭建之WebUI(五)★
- shrio 权限管理filterChainDefinitions过滤器配置
- MyBatis,动态传入表名,字段名的解决办法
- ASP.NET - 上传图片方法(单张)
- 思科_华为_H3C产品对比表
- CentOS6.5下Redis安装与配置
- 清空离线缓存功能的实现,主要分为缓存文件大小的获取、删除缓存文件的实现
- Unity和Android交互,按下锁屏键解锁后游戏重新启动问题解决方法
- PHP合并discuz用户脚本的方法
- 南邮 OJ 1085 A + B Problem (2)
- 单例模式的多种写法