im聊天源代码java im聊天软件源码
如何用java开发基于jabber的IM软件
Jabber对于即时消息是一个开放的、基于XML的数据模型和协议。联系不断增加的基于Jabber开放资源和商业产品的数目,这种协议提供了摆脱即时消息服务器所有权束缚的一种方法。多种多样的开放资源Java APIs能够帮助你建立基于Jabber的服务器并将即时消息整合到你的应用程序中去。在这篇文章中专门阐述了这一点。
创新互联公司是一家专业提供田家庵企业网站建设,专注与网站建设、成都做网站、H5技术、小程序制作等业务。10年已为田家庵众多企业、政府机构等服务。创新互联专业的建站公司优惠进行中。
即时消息作为个人——个人通迅工具取得了显著的成功。在有些地方它已经作为在线联系的首选方法取代了email。现在,开发者正将这一技术应用到应用程序——个人和应用程序——应用程序通迅上。
直到最近,也只有少数服务提供商掌握了这一技术。通常流行的即时消息服务是建立在所有权协议基础上的通迅孤岛。实施面临一个困难的决策:支持多协议或锁定到一个单独的。不管哪种选择,实现都必须依赖一个属于即时消息(IM)服务提供商的服务器。
开放式协议能够帮助开发者摆脱所有权陷阱。其优势有多种:开放协议鼓励竞争实现的发展(一些开放资源)。他们鼓励广泛采用一种公共协议,这样可以阻止通迅孤岛和服务供应的孤立主义方法的发展。用多种方法,开放协议使因特网成为可能。在即时消息领域,开放协议确保封闭系统及协议不会阻碍基于IM服务器的发展的互操作性。
Jabber是一种针对即时消息和现场服务的开放协议。作为一个公共协议的最主要的侯选者,Jabber有潜力打破所有权在即时消息服务的控制。
这篇文章将解释如何实践发送简单Jabber消息和开发一个简单的基于开放标准及开放资源APIs和产品的布告服务器。
为什么使用Jabber?
Jabber标准和结构帮助创建一个分布式的IM系统,使人联想到分布在因特网上的email系统,用户在本地连接到这些系统。这个方法直接与象AIM(AOL即时信使)、ICQ、MSN(Microsoft网络)及Yahoo这样的流行服务提供商提供的单一系统结构作对,在那里一个单独的中央服务器或集中服务器组提供消息服务。Jabber在其他情形也类似于email结构:Jabber使用一个几乎与基本SMTP(简单邮件传输协议)方案一样的地址方案确定它的终点(人,机器,软件)地址。例如,myname@elogex.com是一个有效的Jabber地址,或使用Jabber说法叫JID(Jabber ID)。因为这些原因,基于Jabber的系统衡量起来好于已存在的专有系统。加之,对于专有即时消息服务的网关允许的协议是必需的。
多种多样的Jabber服务器,包括我们在这篇文章中使用的其中之一,都是自由可使用的,意思就是说你不再需要依赖一个第三方IM服务提供商(第三方Jabber服务对于那些要求第三方主机服务的来说也是有用的)。
标准化
当讨论Jabber标准的益处时,我应该提及IETF IM标准的工作。在写这篇文章时,其IMPPWG(即时消息和现场协议工作组)已有多个RFC有效,其中最重要的是:
·RFC 2778:现场和即时消息模型
·RFC 2779:即时消息/现场协议要求
IMPPWG已经起草了一个名叫CPIM(公共现场和即时消息)协议的因特网标准。Jabber协议也是一个草拟的因特网标准,但不是IMPPWG工作的部份。
Jabber在哪儿适合这一标准工作呢?依照Jabber网站,Jabber是“承诺完全支持任何开放实时消息协议,包括IETF协议”。如果当对于这个IETF协议的支持增长时,Jabber打算将自己定位为IETF协议的领导开放资源的平台。到目前为止,IETF的工作更多地主要集中在收集要求上而不是执行。暂时,Jabber仅是一个带有重要开放资源支持的开放即时消息和现场服务协议。结果,它成为开放即时消息事实上的标准。
另一个值得密切注意的竞争对手是Sun微系统的Jxta协议,另一个基于XML针对peer-to-peer(P2P)应用程序开发者的协议。各种各样的Jxta实施在今天已经能够被提供。但是,由于其起源相对较近,Jxta比起Jabber只有很少的牵引力。
下载并安装
要开始使用Jabber,你首先需要下载必要的工具:你需要一个Jabber服务器,一个Jabber客户端,一个帮助管理和隐藏一些复杂socket处理的API,XML语法分析,消息创建等等。
Jabber服务器
为了运行Jabber,你选择的Jabber服务器不能有问题,自从他们都接受了标准Jabber XML及与终端应用程序通迅以释放负荷,其也是标准Jabber XML。Jabberd,最初的Jabber服务器,是开放资源(但不是基于Java),安装配置简单并在多数平台上都有效,包括Unix、Linux、Windows和Mac OS X。JabaServer开放资源方案也值得提及,但现在,这些基于Java的方案仍不如Jabberd成熟。同时,JabaServer安装不怎么简单易懂,因为你必须下载、安装并配置一个第三方数据库,加上创建必需的数据库规划。
对于这篇文章的例子,我选择Jabberd。当二进制及源下载对于jabberd都有效时,我就不在这儿描述怎样建立一个源发布。除非你真想自己编译,可以从jabberd 主页下载二进制发布。在Windows平台上安装是相对容易的。发布是一个.exe程序,按照安装向导一步一步执行。
安装完成后,你无需配置。在Windows2000,不要求配置。只要双击二进制程序就可启动服务器。
用户代理/客户
我决定使用Exodus客户端,对于这个方案这是另一个开放资源技术。我尤其喜欢Exodus的调试标签,可以允许你正确地查看客户发送和接收的XML。另外你能够作为纯粹的XML键入Jabber消息并将它们发送给服务器。所有这些都证明用Jabber协议和服务器测试的有用性。
Exodus的安装简单易懂。下载Exodus 压缩文件(我在文章中使用的是0.6版本)。将文件直接解压到你想要安装客户端的目录。在这个版本中,文件是些简单的二进制文件和一个.dll文件。你可以从 Muse 主页下载Muse API。
发送你的第一个Jabber消息
要发送一个Jabber即时消息,你必须初始化Muse Jabber API。通过创建一个JabberContext 类的实例来完成,接下来使用内容作为一个参数到Jabber session factory类的createSession()方法:
1 //初始化Jabber context
2 JabberContext jabberContext = new JabberContext("user", "pass", "localhost");
4 //创建一个Jabber session factory的实例
5 Jabber jabber = new Jabber();
6 //创建新会话
7 JabberSession jabberSession = jabber.createSession(jabberContext);
上面的例子在第2行显示了一个新context的创建。JabberContext存储了指定的用户相关信息(用户名、密码、用户地址)以及稍后要使用context建立session时包含的一个唯一的会话标识。为了阐述意图,我直接使用了username、password和server。
在第5行,一个Jabber session factory被创建,我们在第7行使用它创建了一个新的JabberSession,Muse进入由Jabber服务器提供的服务的主要接口。服务器的主要服务是:
·连接服务: 从Jabber服务器连接和断开
·用户服务: 针对用户鉴定及注册
·现场服务: 接收从其它用户/服务来的及你自己广播的现场信息
·登记表服务: 密友列表或地址薄
·聊天服务: 发送多种类型的消息—组聊、私聊、标题等等
·服务器服务: 获得与由这个Jabber服务器提供的服务相关的信息
·客户服务: 获得关于其他用户的信息,比如用户登录的最后时间
现在我们已经有了一个已经初始化的Jabber session,我们能够用它在我们才创建的JabberSession对象中使用connect()方法去连接到Jabber 服务器:
8 //连接到服务器
9 jabberSession.connect("localhost", 5222);
要连接到一个Jabber服务器,我们指定地址及在指定服务器上的机器端口号。标准来说,缺省Jabber端口是5222。
现在JabberSession已经连接到服务器,我们能够在我们的服务中用login()方法登录:
10 //登录到Jabber服务器
11 jabberSession.getUserService().login();
在第11行,我们使用JabberSession获得一个到UserService的引用,接下来在我们服务中调用login()方法。注意方法自身不指定任何用户信息。当在上面第7行JabberSession被创建时login()从与JabberSession相关的JabberContext中获得这些信息。
现在我们已经成功登录到Jabber服务器,我们能够开始发送和接收消息。下面代码段显示了如何构造一个简单的标题风格的消息:
12 //构造测试消息
13 JabberChatMessage msg = new
14 JabberChatMessage(JabberChatMessage.TYPE_HEADLINE);
15 msg.setSubject("Hello world");
16 msg.setBody("Hello world");
17 msg.setTo("user2@localhost");
在第13行,我们创建了一个JabberChatMessage实例。单个参数指定了我们要求的消息类型:TYPE_HEADLINE。JabberChatMessage类的名字容易引起误解,实际上,它可以用来包含在Jabber协议中定义的消息的任何四种类型—普通、聊天、标题及错误。在第15行,setSubject()和setBody()分别指定主题和内容。最后,setTo()在第17行设置消息接收器的JID。
在封装下,JabberChatMessage将所有这些信息转换成一个内在的DOM(文档对象模型)树,这样当我们已经准备好发送消息给Jabber服务器时能够轻松产生XML。
最后步骤:用sendMessage()方法发送消息:
18 //发送消息
19 jabberSession.sendMessage(msg);
在封装下
依据上面例子所得的事实,Muse API有效地隐藏了与连接管理和XML语法分析有关的所有细节,因此允许你集中精力在手边的任务上:创建一个消息服务。然而,理解一些基础协议交换证明是有用的。让我们关注一下当我们连接到服务器时发生的XML交换,登录,并象上面代码描述的一样发送消息。在下面的XML交换中,被客户接收的消息(我们例子代码)带了RECV前缀,送到服务器的消息带有SEND前缀:
SEND: ?xml version="1.0" encoding="UTF-8" ?
stream:stream to="localhost"
xmlns="jabber:client"
xmlns:stream=""
RECV: stream:stream from="localhost" id="3D160545"
所有的Jabber交换都发生在一个XML流的上下文。在我们客户与Jabber服务器之间连接的生命期间,两个完全的XML文档在一个时间传输一个片段。上面显示的最初交换允许客户开始发送XML流文档到服务器并且服务器开始发送XML流文档到客户。
下面,一个要求鉴定的信息被发送给服务器:
SEND: iq xmlns="jabber:client" type='get' id='id_10028'
query xmlns="jabber:iq:auth"
usernameuser/username
/query
/iq
RECV: iq xmlns="jabber:client" type='result' id='id_10028'
query xmlns="jabber:iq:auth"
usernameuser/username
password /
digest/
sequence482/sequence
token3D15E63A/token
resource /
/query
/iq
在用户鉴定程序前述那段显示了第一次交换。开始,客户向服务器询问哪种鉴定方式对于给定用户是有效的。服务器段用下面的鉴定方法回答:
·Plain 文本:password /标签
·零知识鉴定:使用sequence和token标签
·digest/:象plain文本,但密码是SHA-1 (安全无序运算法则)-用用户的plain文本密码进行编码
我们实际上使用digest/,象下面代码段描述的一样:
SEND: iq xmlns="jabber:client" type='set' id='id_10030'
query xmlns="jabber:iq:auth"
usernameuser/username
hash425c73373237061edcc5f23ba239c6cc69556f5c/hash
resourceHome/resource
/query
/iq
RECV: iq xmlns="jabber:client" type='result' id='id_10030'/iq
在这一点,用户连接到服务器并能够开始发送和接收消息:
SEND: message xmlns="jabber:client" type='headline'
id='id_10032' to='user2@localhost'
thread xmlns="jabber:client"id_10033/thread
subject xmlns="jabber:client"Hello world/subject
body xmlns="jabber:client"Hello world/body
/message
上面片段显示了我们发送给接收者user2@localhost的测试标题消息。
你可能已经注意到在前述协议段有一个重复出现元素:ID标签。因为session能够由多个异步会话组成,ID标签匹配查询并响应。
接收消息
自从这篇文章的主要方向是向你显示如何开发一个报警系统,我就很少注意消息接收。然而,为了完整性的利益,我应该讨论在Muse API中处理接收消息的一些有用特性。另外,因为报警服务是被登录到Jabber服务器的用户执行的,你能够适当地期望一些消息接收者试图与发送者通信。
Muse使用一个listener附在session上以接收进入消息的提示。下面代码显示了如何创建一个listener并将其附到session——listener实际上附加到连接上,但自从我们的接口是在session级别并且JabberSession类有一个便利的方法添加一个listener,我们就将其附加到session:
1 jabberSession.addMessageListener(
2 new JabberMessageListener() {
3 public void messageReceived(JabberMessageEvent event) {
4 if (event.getMessageType() == JabberCode.MSG_CHAT ) {
5 JabberChatMessage msg =
6 (JabberChatMessage)event.getMessage();
7 JabberChatMessage reply = new
8 JabberChatMessage(JabberChatMessage.TYPE_HEADLINE);
9 reply.setTo(msg.getFrom());
10 reply.setSubject("Re: "+msg.getSubject());
11 reply.setBody(
12 "I'm just a sender: please send messages to someone else");
13
14 //发送消息
15 jabberSession.sendMessage(reply);
16 }
17 }
18 }
19 );
客户能够添加几个消息listeners,每次一个消息被接收它们都要被调用。典型的,你为要处理的每一个类型的消息添加一个listener。另一个选择:为同一种消息类型但在那些消息中的每一种不同的行为添加多个listeners。然而另一种选择将添加一个要处理所有消息类型的listener。选择依赖于你想完成什么。
在上面的例子中,一个单独的listener被附加。Listener必须是实现JabberMessageListener接口的类的一个实例。这个接口要求一个要被执行的单个方法: void messageReceived(JabberMessageEvent)。当一个消息从服务器被接收时这个方法将被调用。在例子代码中,messageReceived()方法首先检查在第4行接收的消息类型。自从Jabber用户代理使用了MSG_CHAT类型发送消息,就只对这种类型消息才感兴趣。在第5行,Jabber消息从JabberMessageEvent 提取。在第9行通过设置收件人接收消息被用来构成一个给消息发送者的回复并且在第10行拷贝接收消息的主题。一个缺省错误文本被作为消息体在第11行被设置,并且,在第15行,消息使用前面例子同样的方法利用JabberSession对象的sendMessage()方法传输。
试试Jabber
这篇文章提供了一个对于Jabber协议及少量你能够将这一技术应用到你的应用程序中去的开放资源方案的基本介绍。对这个协议有用的应用程序多种多样,并不限于传统P2P感觉的即时消息领域。例如,jogger.jabber.org提供的Jogger,一个允许你通过发送一个消息给Weblog应用程序(blog)就能更新个人网络杂志的有趣服务。Jabber在用户服务应用程序及其它结构的协作类型应用程序同样有很大的影响。
象上面例子所显示的一样,你使用一个API如Muse或JabberBeans在少许几行Java代码中就能够完成即时消息功能。记住我不能掩盖一些Jabber其它重要的特征,如现场服务和登记表管理,这些在使用时都是相关的。另一个重要的特征是Jabber服务器的模块性和可扩展性,它允许一个开发者创建新的服务直接整合进服务器。
求java网络聊天室(B/S模式)程序代码
共四个java文件,源代码如下:
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.io.*;
import java.util.Hashtable;
public class ChatArea extends Panel implements ActionListener,Runnable
{
Socket socket=null;
DataInputStream in=null;
DataOutputStream out=null;
Thread threadMessage=null;
TextArea 谈话显示区,私聊显示区=null;
TextField 送出信息=null;
Button 确定,刷新谈话区,刷新私聊区;
Label 提示条=null;
String name=null;
Hashtable listTable;
List listComponent=null;
Choice privateChatList;
int width,height;
public ChatArea(String name,Hashtable listTable,int width,int height)
{
setLayout(null);
setBackground(Color.orange);
this.width=width;
this.height=height;
setSize(width,height);
this.listTable=listTable;
this.name=name;
threadMessage=new Thread(this);
谈话显示区=new TextArea(10,10);
私聊显示区=new TextArea(10,10);
确定=new Button("送出信息到:");
刷新谈话区=new Button("刷新谈话区");
刷新私聊区=new Button("刷新私聊区");
提示条=new Label("双击聊天者可私聊",Label.CENTER);
送出信息=new TextField(28);
确定.addActionListener(this);
送出信息.addActionListener(this);
刷新谈话区.addActionListener(this);
刷新私聊区.addActionListener(this);
listComponent=new List();
listComponent.addActionListener(this);
privateChatList=new Choice();
privateChatList.add("大家(*)");
privateChatList.select(0);
add(谈话显示区);
谈话显示区.setBounds(10,10,(width-120)/2,(height-120));
add(私聊显示区);
私聊显示区.setBounds(10+(width-120)/2,10,(width-120)/2,(height-120));
add(listComponent);
listComponent.setBounds(10+(width-120),10,100,(height-160));
add(提示条);
提示条.setBounds(10+(width-120),10+(height-160),110,40);
Panel pSouth=new Panel();
pSouth.add(送出信息);
pSouth.add(确定);
pSouth.add(privateChatList);
pSouth.add(刷新谈话区);
pSouth.add(刷新私聊区);
add(pSouth);
pSouth.setBounds(10,20+(height-120),width-20,60);
}
public void setName(String s)
{
name=s;
}
public void setSocketConnection(Socket socket,DataInputStream in,DataOutputStream out)
{
this.socket=socket;
this.in=in;
this.out=out;
try
{
threadMessage.start();
}
catch(Exception e)
{
}
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==确定||e.getSource()==送出信息)
{
String message="";
String people=privateChatList.getSelectedItem();
people=people.substring(0,people.indexOf("("));
message=送出信息.getText();
if(message.length()0)
{
try {
if(people.equals("大家"))
{
out.writeUTF("公共聊天内容:"+name+"说:"+message);
}
else
{
out.writeUTF("私人聊天内容:"+name+"悄悄地说:"+message+"#"+people);
}
}
catch(IOException event)
{
}
}
}
else if(e.getSource()==listComponent)
{
privateChatList.insert(listComponent.getSelectedItem(),0);
privateChatList.repaint();
}
else if(e.getSource()==刷新谈话区)
{
谈话显示区.setText(null);
}
else if(e.getSource()==刷新私聊区)
{
私聊显示区.setText(null);
}
}
public void run()
{
while(true)
{
String s=null;
try
{
s=in.readUTF();
if(s.startsWith("聊天内容:"))
{
String content=s.substring(s.indexOf(":")+1);
谈话显示区.append("\n"+content);
}
if(s.startsWith("私人聊天内容:"))
{
String content=s.substring(s.indexOf(":")+1);
私聊显示区.append("\n"+content);
}
else if(s.startsWith("聊天者:"))
{
String people=s.substring(s.indexOf(":")+1,s.indexOf("性别"));
String sex=s.substring(s.indexOf("性别")+2);
listTable.put(people,people+"("+sex+")");
listComponent.add((String)listTable.get(people));
listComponent.repaint();
}
else if(s.startsWith("用户离线:"))
{
String awayPeopleName=s.substring(s.indexOf(":")+1);
listComponent.remove((String)listTable.get(awayPeopleName));
listComponent.repaint();
谈话显示区.append("\n"+(String)listTable.get(awayPeopleName)+"离线");
listTable.remove(awayPeopleName);
}
Thread.sleep(5);
}
catch(IOException e)
{
listComponent.removeAll();
listComponent.repaint();
listTable.clear();
谈话显示区.setText("和服务器的连接已中断\n必须刷新浏览器才能再次聊天");
break;
}
catch(InterruptedException e)
{
}
}
}
}
ChatServer.java
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer
{
public static void main(String args[])
{
ServerSocket server=null;
Socket you=null;
Hashtable peopleList;
peopleList=new Hashtable();
while(true)
{
try
{
server=new ServerSocket(6666);
}
catch(IOException e1)
{
System.out.println("正在监听");
}
try {
you=server.accept();
InetAddress address=you.getInetAddress();
System.out.println("用户的IP:"+address);
}
catch (IOException e)
{
}
if(you!=null)
{
Server_thread peopleThread=new Server_thread(you,peopleList);
peopleThread.start();
}
else {
continue;
}
}
}
}
class Server_thread extends Thread
{
String name=null,sex=null;
Socket socket=null;
File file=null;
DataOutputStream out=null;
DataInputStream in=null;
Hashtable peopleList=null;
Server_thread(Socket t,Hashtable list)
{
peopleList=list;
socket=t;
try {
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
}
catch (IOException e)
{
}
}
public void run()
{
while(true)
{ String s=null;
try
{
s=in.readUTF();
if(s.startsWith("姓名:"))
{
name=s.substring(s.indexOf(":")+1,s.indexOf("性别"));
sex=s.substring(s.lastIndexOf(":")+1);
boolean boo=peopleList.containsKey(name);
if(boo==false)
{
peopleList.put(name,this);
out.writeUTF("可以聊天:");
Enumeration enum=peopleList.elements();
while(enum.hasMoreElements())
{
Server_thread th=(Server_thread)enum.nextElement();
th.out.writeUTF("聊天者:"+name+"性别"+sex);
if(th!=this)
{
out.writeUTF("聊天者:"+th.name+"性别"+th.sex);
}
}
}
else
{
out.writeUTF("不可以聊天:");
}
}
else if(s.startsWith("公共聊天内容:"))
{
String message=s.substring(s.indexOf(":")+1);
Enumeration enum=peopleList.elements();
while(enum.hasMoreElements())
{
((Server_thread)enum.nextElement()).out.writeUTF("聊天内容:"+message);
}
}
else if(s.startsWith("用户离开:"))
{
Enumeration enum=peopleList.elements();
while(enum.hasMoreElements())
{ try
{
Server_thread th=(Server_thread)enum.nextElement();
if(th!=thisth.isAlive())
{
th.out.writeUTF("用户离线:"+name);
}
}
catch(IOException eee)
{
}
}
peopleList.remove(name);
socket.close();
System.out.println(name+"用户离开了");
break;
}
else if(s.startsWith("私人聊天内容:"))
{
String 悄悄话=s.substring(s.indexOf(":")+1,s.indexOf("#"));
String toPeople=s.substring(s.indexOf("#")+1);
Server_thread toThread=(Server_thread)peopleList.get(toPeople);
if(toThread!=null)
{
toThread.out.writeUTF("私人聊天内容:"+悄悄话);
}
else
{
out.writeUTF("私人聊天内容:"+toPeople+"已经离线");
}
}
}
catch(IOException ee)
{
Enumeration enum=peopleList.elements();
while(enum.hasMoreElements())
{ try
{
Server_thread th=(Server_thread)enum.nextElement();
if(th!=thisth.isAlive())
{
th.out.writeUTF("用户离线:"+name);
}
}
catch(IOException eee)
{
}
}
peopleList.remove(name);
try
{
socket.close();
}
catch(IOException eee)
{
}
System.out.println(name+"用户离开了");
break;
}
}
}
}
import java.awt.*;
import java.io.*;
import java.net.*;
import java.applet.*;
import java.util.Hashtable;
ClientChat.java
public class ClientChat extends Applet implements Runnable
{
Socket socket=null;
DataInputStream in=null;
DataOutputStream out=null;
InputNameTextField 用户提交昵称界面=null;
ChatArea 用户聊天界面=null;
Hashtable listTable;
Label 提示条;
Panel north, center;
Thread thread;
public void init()
{
int width=getSize().width;
int height=getSize().height;
listTable=new Hashtable();
setLayout(new BorderLayout());
用户提交昵称界面=new InputNameTextField(listTable);
int h=用户提交昵称界面.getSize().height;
用户聊天界面=new ChatArea("",listTable,width,height-(h+5));
用户聊天界面.setVisible(false);
提示条=new Label("正在连接到服务器,请稍等...",Label.CENTER);
提示条.setForeground(Color.red);
north=new Panel(new FlowLayout(FlowLayout.LEFT));
center=new Panel();
north.add(用户提交昵称界面);
north.add(提示条);
center.add(用户聊天界面);
add(north,BorderLayout.NORTH);
add(center,BorderLayout.CENTER);
validate();
}
public void start()
{
if(socket!=nullin!=nullout!=null)
{ try
{
socket.close();
in.close();
out.close();
用户聊天界面.setVisible(false);
}
catch(Exception ee)
{
}
}
try
{
socket = new Socket(this.getCodeBase().getHost(), 6666);
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
}
catch (IOException ee)
{
提示条.setText("连接失败");
}
if(socket!=null)
{
InetAddress address=socket.getInetAddress();
提示条.setText("连接:"+address+"成功");
用户提交昵称界面.setSocketConnection(socket,in,out);
north.validate();
}
if(thread==null)
{
thread=new Thread(this);
thread.start();
}
}
public void stop()
{
try
{
socket.close();
thread=null;
}
catch(IOException e)
{
this.showStatus(e.toString());
}
}
public void run()
{
while(thread!=null)
{
if(用户提交昵称界面.get能否聊天()==true)
{
用户聊天界面.setVisible(true);
用户聊天界面.setName(用户提交昵称界面.getName());
用户聊天界面.setSocketConnection(socket,in,out);
提示条.setText("祝聊天愉快!");
center.validate();
break;
}
try
{
Thread.sleep(100);
}
catch(Exception e)
{
}
}
}
}
InputNameTextField。java
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.io.*;
import java.util.Hashtable;
public class InputNameTextField extends Panel implements ActionListener,Runnable
{
TextField nameFile=null;
String name=null;
Checkbox male=null,female=null;
CheckboxGroup group=null;
Button 进入聊天室=null,退出聊天室=null;
Socket socket=null;
DataInputStream in=null;
DataOutputStream out=null;
Thread thread=null;
boolean 能否聊天=false;
Hashtable listTable;
public InputNameTextField(Hashtable listTable)
{
this.listTable=listTable;
nameFile=new TextField(10);
group=new CheckboxGroup();
male=new Checkbox("男",true,group);
female=new Checkbox("女",false,group);
进入聊天室=new Button("进入");
退出聊天室=new Button("退出");
进入聊天室.addActionListener(this);
退出聊天室.addActionListener(this);
thread=new Thread(this);
add(new Label("昵称:"));
add(nameFile);
add(male);
add(female);
add(进入聊天室);
add(退出聊天室);
退出聊天室.setEnabled(false);
}
public void set能否聊天(boolean b)
{
能否聊天=b;
}
public boolean get能否聊天()
{
return 能否聊天;
}
public String getName()
{
return name;
}
public void setName(String s)
{
name=s;
}
public void setSocketConnection(Socket socket,DataInputStream in,DataOutputStream out)
{
this.socket=socket;
this.in=in;
this.out=out;
try{
thread.start();
}
catch(Exception e)
{
nameFile.setText(""+e);
}
}
public Socket getSocket()
{
return socket;
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==进入聊天室)
{
退出聊天室.setEnabled(true);
if(能否聊天==true)
{
nameFile.setText("您正在聊天:"+name);
}
else
{
this.setName(nameFile.getText());
String sex=group.getSelectedCheckbox().getLabel();
if(socket!=nullname!=null)
{
try{
out.writeUTF("姓名:"+name+"性别:"+sex);
}
catch(IOException ee)
{
nameFile.setText("没有连通服务器"+ee);
}
}
}
}
if(e.getSource()==退出聊天室)
{
try
{
out.writeUTF("用户离开:");
}
catch(IOException ee)
{
}
}
}
public void run()
{
String message=null;
while(true)
{
if(in!=null)
{
try
{
message=in.readUTF();
}
catch(IOException e)
{
nameFile.setText("和服务器断开"+e);
}
}
if(message.startsWith("可以聊天:"))
{
能否聊天=true;
break;
}
else if(message.startsWith("聊天者:"))
{
String people=message.substring(message.indexOf(":")+1);
listTable.put(people,people);
}
else if(message.startsWith("不可以聊天:"))
{
能否聊天=false;
nameFile.setText("该昵称已被占用");
}
}
}
}
速求用JAVA语言写聊天室的源代码
【ClientSocketDemo.java 客户端Java源代码】
import java.net.*;
import java.io.*;
public class ClientSocketDemo
{
//声明客户端Socket对象socket
Socket socket = null;
//声明客户器端数据输入输出流
DataInputStream in;
DataOutputStream out;
//声明字符串数组对象response,用于存储从服务器接收到的信息
String response[];
//执行过程中,没有参数时的构造方法,本地服务器在本地,取默认端口10745
public ClientSocketDemo()
{
try
{
//创建客户端socket,服务器地址取本地,端口号为10745
socket = new Socket("localhost",10745);
//创建客户端数据输入输出流,用于对服务器端发送或接收数据
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
//获取客户端地址及端口号
String ip = String.valueOf(socket.getLocalAddress());
String port = String.valueOf(socket.getLocalPort());
//向服务器发送数据
out.writeUTF("Hello Server.This connection is from client.");
out.writeUTF(ip);
out.writeUTF(port);
//从服务器接收数据
response = new String[3];
for (int i = 0; i response.length; i++)
{
response[i] = in.readUTF();
System.out.println(response[i]);
}
}
catch(UnknownHostException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
//执行过程中,有一个参数时的构造方法,参数指定服务器地址,取默认端口10745
public ClientSocketDemo(String hostname)
{
try
{
//创建客户端socket,hostname参数指定服务器地址,端口号为10745
socket = new Socket(hostname,10745);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
String ip = String.valueOf(socket.getLocalAddress());
String port = String.valueOf(socket.getLocalPort());
out.writeUTF("Hello Server.This connection is from client.");
out.writeUTF(ip);
out.writeUTF(port);
response = new String[3];
for (int i = 0; i response.length; i++)
{
response[i] = in.readUTF();
System.out.println(response[i]);
}
}
catch(UnknownHostException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
//执行过程中,有两个个参数时的构造方法,第一个参数hostname指定服务器地址
//第一个参数serverPort指定服务器端口号
public ClientSocketDemo(String hostname,String serverPort)
{
try
{
socket = new Socket(hostname,Integer.parseInt(serverPort));
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
String ip = String.valueOf(socket.getLocalAddress());
String port = String.valueOf(socket.getLocalPort());
out.writeUTF("Hello Server.This connection is from client.");
out.writeUTF(ip);
out.writeUTF(port);
response = new String[3];
for (int i = 0; i response.length; i++)
{
response[i] = in.readUTF();
System.out.println(response[i]);
}
}
catch(UnknownHostException e){e.printStackTrace();}
catch(IOException e){e.printStackTrace();}
}
public static void main(String[] args)
{
String comd[] = args;
if(comd.length == 0)
{
System.out.println("Use localhost(127.0.0.1) and default port");
ClientSocketDemo demo = new ClientSocketDemo();
}
else if(comd.length == 1)
{
System.out.println("Use default port");
ClientSocketDemo demo = new ClientSocketDemo(args[0]);
}
else if(comd.length == 2)
{
System.out.println("Hostname and port are named by user");
ClientSocketDemo demo = new ClientSocketDemo(args[0],args[1]);
}
else System.out.println("ERROR");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
【ServerSocketDemo.java 服务器端Java源代码】
import java.net.*;
import java.io.*;
public class ServerSocketDemo
{
//声明ServerSocket类对象
ServerSocket serverSocket;
//声明并初始化服务器端监听端口号常量
public static final int PORT = 10745;
//声明服务器端数据输入输出流
DataInputStream in;
DataOutputStream out;
//声明InetAddress类对象ip,用于获取服务器地址及端口号等信息
InetAddress ip = null;
//声明字符串数组对象request,用于存储从客户端发送来的信息
String request[];
public ServerSocketDemo()
{
request = new String[3]; //初始化字符串数组
try
{
//获取本地服务器地址信息
ip = InetAddress.getLocalHost();
//以PORT为服务端口号,创建serverSocket对象以监听该端口上的连接
serverSocket = new ServerSocket(PORT);
//创建Socket类的对象socket,用于保存连接到服务器的客户端socket对象
Socket socket = serverSocket.accept();
System.out.println("This is server:"+String.valueOf(ip)+PORT);
//创建服务器端数据输入输出流,用于对客户端接收或发送数据
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
//接收客户端发送来的数据信息,并显示
request[0] = in.readUTF();
request[1] = in.readUTF();
request[2] = in.readUTF();
System.out.println("Received messages form client is:");
System.out.println(request[0]);
System.out.println(request[1]);
System.out.println(request[2]);
//向客户端发送数据
out.writeUTF("Hello client!");
out.writeUTF("Your ip is:"+request[1]);
out.writeUTF("Your port is:"+request[2]);
}
catch(IOException e){e.printStackTrace();}
}
public static void main(String[] args)
{
ServerSocketDemo demo = new ServerSocketDemo();
}
}
IM即时通讯聊天社交APP源码,交友APP源码
交友APP源码 IM带音视频源码Uniapp 即时通讯安卓苹果APP源码
前端开发语言:VUE( 安卓,IOS,WEB为一套前端代码)
服务器端开发语言: PHP+WebSocket
数据库:MySql + mongodb
前端打包工具:Hbuilder
服务器搭建工具:宝塔 + Xshell
短信接口: 支持阿里云
支付接口:支持支付宝
服务器配置: 4核8G宽带10兆以上
服务器系统:Linux Centos 7.6 64位
基本功能说明:
1.发消息:语音、图片、视频、文字、表情、表情包、文件、名片等。
2.聊天:单聊、群聊。
3.自定义消息:发红包、转账。
4.聊天记录:清空聊天记录、群管理、加群二维码控制是否可加。
5.自定义添加链接。
6.我的钱包:后台可以充值、用户充值、提现等。
7.创建群:可任意创建群,群成员数量不受限制,好友数量不受限。
8.群功能:设置群二维码、群公告、群共享文件、顶置聊天、消息免打扰,屏蔽群信息、禁言、举报、群管理、查找聊天记录、禁止全员相互加好友、清空聊天记录等。
9.好友聊天:文字、语音、音视频通话、收藏、照片、小视频、各种表情、传送文件、发送位置、引用回复、撤回、复制、删除、收藏、撤回、录制、多选、发红包,转账等。
10.生活圈动态:可以发送图文、语音、视频、可点赞,评论、举报等。
11.会员登录:注册登录、短信登录。
12.账号设置:修改密码、语言切换、字体设置、隐私设置、安全设置、一键群发好友消息等。
13.用户管理:登录时间、登陆IP、更换头像、更换名称、设置密码、批量生成用户。
14.后台功能: 管理员列表、系统设置、用户管理、群组管理、通讯录管理、财务管理、会话管理、自定义网站、手机通讯录
了解更多源码内容,您可以私信我!
如果您也喜欢这篇文章,记得点赞+关注+评论+转发哟![比心][比心][比心]
分享标题:im聊天源代码java im聊天软件源码
文章URL:http://azwzsj.com/article/hpiigj.html