`

多用户的P2P在线聊天程序,完全源码 连载一 监听新用户加入

阅读更多

本例开发实现了一个多用户的P2P在线聊天程序,C/S结构,客户端可发送消息,然后其他的用户接收到该消息并将其显示在界面中,服务器对信息进行有关处理并向适当的用户发送,同时在服务器端还将显示所有的在线用户,网络管理员即服务器端管理员可选中某用户并将其踢出该聊天室。以上功能的完成主要分为以下几个步骤。

 

开发环境Eclipse3.2 —— Java开发的IDE工具,用于编写服务端和客户端的功能实现类。

 

一  Server端

 

1 监听新用户加入(SimpleServer.java)

 

新建-〉工程(名为Chat),新建包(名为Server),新建File,名为SimpleServer.java。

在该类中,首先创建一Frame对象,而后再Frame类中添加两个按钮button1(“关闭”)和button2(“踢出”),一个列表框list1以及一个组合框groupBox1,并利用paneLayout进行适当的布局。完成main函数用来显示主窗体对象:

  public static void main(String[] args)

    {

        try

        {

            SimpleServer simpleServer=new SimpleServer(4321);

            simpleServer.setLocation(100,50);

            simpleServer.setSize(400,300);

            simpleServer.show();

         }

        catch(Exception e)

        {

            System.out.print("GotError");

            e.printStackTrace() ;

        }

    }

在主程序中创建一个无限循环,用来监听指定端口查看是否有新的用户加入到聊天室,每监听到一个新的用户则初始化建立一个Socket连接,并作为一个单独的线程保持与该用户的所有联系。

首先定义个ServerSocket,ServerSocket就是服务器端的Socket,它可以监听客户端的连接,而同普通Socket不同就是它的实例化不需要指定主机名而只需要执行特定的端口(若不指定系统就会自动赋予)就可以了:

  try

    {

    protected ServerSocket listenSock;

     int listenPort=4321;

    listenSock=new ServerSocket(listenPort);

    }

   

   catch(Exception e)

   {

       System.out.println(e.toString());

}

在服务器端已经初始化了一个4321端口用来监听客户端所发送过来的信息,但必须确定服务器该端口是否可用,如果该端口已经被占用则将抛出一个异常而导致该端口初始化失败。初始化该端口之后,则可以加入一个无限循环用来监听消息:

public void waitForClients()

    {

        while(true)

        {

            try

            {

                Socket newClient=listenSock.accept() ;

                newConn=new ServerConn(this,newClient);

                users.addElement(newConn);

            }

            catch(Exception bad)

            {

                bad.printStackTrace() ;

            }

        }

  }

当服务器监听到一个新的客户加入时,便同客户端建立一个Socket连接,同时实例化一个用来控制该用户的实例ServerConn,并将该用户实例加入一个矢量表中,该矢量表存放所有的用户实例对象。

 

      在该实例中网络管理员可以在服务器端对聊天中的在线成员进行简单的维护,也就是可以强制将该用户踢出聊天室。在主窗体中的button2的实现方法如下所示:

   void button2_actionPerformed(ActionEvent e)

   {

        String str=list1.getSelectedItem();

        StringTokenizer st=new StringTokenizer(str,"---");

        String userIP=st.nextToken();

        String userName=st.nextToken();

        for(int i=0;i<=users.size();i++)

       {

           ServerConn conn=(ServerConn)users.elementAt(i);

          String ip1=conn.reader.userIP;

          String userName1=conn.reader.userName;

          if(userIP.equals(ip1)&&userName.equals(userName1))

          {

             list1.remove(str);

             conn.sendString("quit");

             conn.reader.stop();

             users.removeElement(conn);

          }

       }

}

通过循环确定当前网络管理员在列表中所选择的用户实例,然后向该用户发送“quit”指令,该指令在客户端将解释执行并强制将该用户从聊天室中踢出;同时服务器端该用户线程停止,用户列表中删除该用户并将该用户实例从矢量表中删除。

 

最后得到主窗体如程序清单SimpleServer.java所示。
程序清单:

package Server;

import java.awt.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.awt.event.*;
import com.borland.jbcl.layout.*;
import com.borland.jbcl.control.*;
import java.lang.String;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2010</p>
 *
 * <p>Company: </p>
 *
 * @author www.jianfei5u.com
 * @version 1.0
 */
public class SimpleServer extends Frame {
    protected ServerConn newConn;
    protected ServerSocket listenSock;
    GroupBox groupBox1=new GroupBox();
    Button button1=new Button() ;
    Button button2=new Button() ;
    PaneLayout paneLayout1=new PaneLayout();
    java.awt.List list1=new java.awt.List();
    PaneLayout paneLayout2=new PaneLayout();
    Vector users=new Vector();


    public SimpleServer(int listenPort) throws Exception {
        listenSock=new ServerSocket(listenPort);
        try {
            jbInit();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    public void waitForClients()
    {
        while(true)
        {
            try
            {
                Socket newClient=listenSock.accept() ;
                newConn=new ServerConn(this,newClient);
                users.addElement(newConn);
            }
            catch(Exception bad)
            {
                bad.printStackTrace() ;
            }
        }
    }

    public synchronized String processString(String instr)
    {
        return instr;
    }

    public static void main(String[] args)
    {
        try
        {
            SimpleServer simpleServer=new SimpleServer(4321);
            simpleServer.setLocation(100,50);
            simpleServer.setSize(400,300);
            simpleServer.show();
            simpleServer.waitForClients() ;
        }
        catch(Exception e)
        {
            System.out.print("GotError");
            e.printStackTrace() ;
        }
    }

    public SimpleServer()
    {
        try
        {
            jbInit();
        }
        catch(Exception e)
        {
            e.printStackTrace() ;
        }
    }

    private void jbInit() throws Exception {
        this.setLayout(paneLayout1);
        this.setSize(new Dimension(503,354));
        this.setTitle("服务器端");

        groupBox1.setLayout(paneLayout2);
        groupBox1.setLabel("在线用户");

        button1.setLabel("关闭");
        button1.addActionListener(new SimpleServer_button1_actionAdapter(this));
        button2.setLabel("踢出");
        button2.addActionListener(new SimpleServer_button2_actionAdapter(this));

        groupBox1.add(list1,new PaneConstraints("list1","list11",
        PaneConstraints.ROOT,1.0f));
        this.add(groupBox1,new PaneConstraints("groupBox1","groupBox1",
        PaneConstraints.ROOT,0.5f));
        this.add(button2,new PaneConstraints("button2","groupBox1",
        PaneConstraints.BOTTOM,0.1469534f));
        this.add(button1,new PaneConstraints("button1","button2",
        PaneConstraints.RIGHT,0.5303644f));
    }

    void tellEveryone(String str)
    {
        for(int i=0;i<=users.size();i++)
        {
            ServerConn conn=(ServerConn)users.elementAt(i);
            conn.sendString(str);
        }
    }

    void removeServerConn(String ip,String userName)
    {
        for(int i=0;i<=users.size();i++)
        {
            ServerConn conn=(ServerConn)users.elementAt(i);
           String ip1=conn.reader.userIP;
           String userName1=conn.reader.userName;
           if(ip.equals(ip1)&&userName.equals(userName1))
           users.removeElement(conn);
        }

    }

    void button2_actionPerformed(ActionEvent e)
    {
        String str=list1.getSelectedItem();
        StringTokenizer st=new StringTokenizer(str,"---");
        String userIP=st.nextToken();
        String userName=st.nextToken();
        for(int i=0;i<=users.size();i++)
       {
           ServerConn conn=(ServerConn)users.elementAt(i);
          String ip1=conn.reader.userIP;
          String userName1=conn.reader.userName;
          if(userIP.equals(ip1)&&userName.equals(userName1))
          {
             list1.remove(str);
             conn.sendString("quit");
             conn.reader.stop();
             users.removeElement(conn);
          }
       }


    }

    void button1_actionPerformed(ActionEvent e)
   {
       System.exit(0);
   }
}
class SimpleServer_button2_actionAdapter implements java.awt.event.ActionListener
{
    SimpleServer adaptee;

    SimpleServer_button2_actionAdapter(SimpleServer adaptee)
    {
        this.adaptee =adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.button2_actionPerformed(e);
    }
}

class SimpleServer_button1_actionAdapter implements java.awt.event.ActionListener
{
    SimpleServer adaptee;

    SimpleServer_button1_actionAdapter(SimpleServer adaptee)
    {
        this.adaptee =adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.button1_actionPerformed(e);
    }
}

 

未完待续。。。

下一集 编写用户实例类 地址 http://java161.iteye.com/blog/616123

分享到:
评论
9 楼 zha_zi 2010-03-17  
哥们你整理好弄一个包上传上,加上注释,
原理分析图片看不见是不是上传的原理
8 楼 lzyzizi 2010-03-17  
随便看了下,没看出来哪里用到了P2P。
server没有线程池的管理?
长链接可以考虑NIO实现。
7 楼 wxq594808632 2010-03-17  
提点意见先.
代码注释
代码样式
6 楼 mindxw 2010-03-17  
建议楼主以后发代码的时候至少写上注释,还有最好将源码文件打包上传,还有最好画流程图,还有就算懒得画流程图,那么画个思路图也可以啊。

习惯啊,同学们!
5 楼 我奋斗 2010-03-16  
好东东,mark一下。
4 楼 hailiang0901 2010-03-16  
wujiazhao88 写道
用组播可以去掉服务器端

组播不可以在广域网上跑,去研究下组播吧。
3 楼 wujiazhao88 2010-03-16  
用组播可以去掉服务器端
2 楼 qiren83 2010-03-16  
好贴 正好学习下 CS和多线程 通信技术

先去面试 晚上回来看

相关推荐

    基于Java的P2P多用户在线聊天室项目源码

    该项目是使用Java编程语言开发的一款P2P(peer-to-peer)多用户在线聊天室系统,旨在实现用户间的实时通信。P2P网络架构在这种场景下意味着每个用户都可以既是客户端也是服务器,通过直接与其他用户建立连接进行信息...

    基于java的开发源码-P2P-多用户在线聊天室(Java源码).zip

    基于java的开发源码-P2P--多用户在线聊天室(Java源码).zip 基于java的开发源码-P2P--多用户在线聊天室(Java源码).zip 基于java的开发源码-P2P--多用户在线聊天室(Java源码).zip 基于java的开发源码-P2P--多...

    P2P--多用户在线聊天室(Java源码)

    标题"“P2P--多用户在线聊天室(Java源码)”"揭示了我们讨论的主题是一个基于P2P技术构建的、支持多用户同时在线交流的聊天室系统,其核心实现是用Java编程语言编写的。这里的"P2P"指的是对等网络,它是一种分布式...

    P2P点对点聊天 源码

    《P2P点对点聊天源码解析与技术探讨》 在信息技术日新月异的今天,P2P(Peer-to-Peer)技术以其独特的分布式特性,在网络通信领域展现出强大的生命力。P2P点对点聊天系统是P2P技术在即时通讯应用中的典型实例,它...

    基于P2P UDP的局域网聊天工具源码

    【标题】"基于P2P UDP的局域网聊天工具源码" 描述了一款使用P2P(点对点)技术并通过UDP(用户数据报协议)进行通信的局域网聊天工具。这款源码提供了深入理解P2P网络和UDP通信在实际应用中的机会,适合开发者学习和...

    P2P聊天程序(JAVA)

    【P2P聊天程序(JAVA)】是一种网络通信应用程序,它使用对等网络(P2P,Peer-to-Peer)架构来实现用户之间的实时交流。P2P技术允许网络中的每个节点既是客户端也是服务器,因此在聊天程序中,每个用户都可以发送和...

    用Java Socket实现一个简单的基于P2P范型的即时聊天系统。

    为了支持多用户聊天,我们需要在每个节点上维护一个用户列表,并且为每个连接创建一个新的线程来处理单独的聊天会话。这样,节点可以同时接收和发送多个会话的数据,实现了多人聊天的功能。 3. **用户自由加入和...

    P2P--多用户在线聊天室(Java源码).rar

    P2P--多用户在线聊天室(Java源码).rar

    P2P-多用户在线聊天室(Java源码).zip

    标题和描述中提到的"P2P-多用户在线聊天室(Java源码)"是一个基于P2P(Peer-to-Peer)技术实现的多人在线聊天系统,其核心是使用Java编程语言编写的源代码。P2P网络是一种分布式网络架构,其中每个参与者既是客户端...

    P2P-多用户在线聊天室(Java源码).rar

    标题中的"P2P-多用户在线聊天室(Java源码)"表明这是一个基于P2P技术的、允许多个用户实时交流的在线聊天室系统,其核心编程语言是Java。P2P,即对等网络,是一种分布式网络架构,其中每个参与者既是服务的消费者也...

    C#p2p源码,聊天程序百分百可用的源码

    C# P2P(peer-to-peer)源码是用于构建聊天程序的一种编程资源,它允许开发者创建无需中心服务器,可以直接在参与者之间交换信息的应用。P2P架构在互联网上广泛应用,因为它可以有效地分发流量,降低单一服务器的...

    P2P聊天源码 IM

    P2P(Peer-to-Peer)聊天源码是一种实现用户间直接通信的技术,它与传统的客户端-服务器(C/S)架构不同,P2P网络中的每个节点既是服务提供者也是服务消费者。在IM(Instant Messaging)即时通讯系统中,P2P技术被...

    WINFORM P2P语言聊天系统源码

    这是一款基于WinForm技术的p2p语言聊天系统,使用udp传送语音和文本等信息。在这个系统中没有服务端和客户端,相互通讯都是直接相互联系的。能够很好的实现效果。 二、菜单功能 该源码是一种人与人进行交流的工具...

    JAVA源码P2P-多用户在线聊天室(Java源码)

    JAVA源码P2P-多用户在线聊天室(Java源码)

    VC p2p聊天室源码

    【VC点对点聊天室源码】是一种基于Visual C++(简称VC)开发的P2P(Peer-to-Peer)网络通信系统,主要用于实现用户之间的实时聊天功能。在这个项目中,我们将深入探讨P2P技术在聊天应用中的实现,以及VC编程的相关...

    基于Java的P2P--多用户在线聊天室(Java源码).zip

    "基于Java的P2P--多用户在线聊天室(Java源码).zip" 这个标题表明我们所面对的是一个使用Java编程语言开发的P2P(Peer-to-Peer)网络应用,具体实现了一个多用户可以同时参与的在线聊天室。P2P技术是一种分布式网络...

    精选_基于Qt实现的P2P聊天程序_源码打包

    "精选_基于Qt实现的P2P聊天程序_源码打包" 这个标题揭示了我们讨论的核心内容,即一个使用Qt框架开发的点对点(P2P)聊天应用程序。"精选"表明这是一份高质量或具有代表性的代码库,而"源码打包"意味着我们可以获得...

    P2P聊天程序C#源代码

    【标题】"P2P聊天程序C#源代码"是一个基于C#编程语言实现的点对点(Peer-to-Peer,简称P2P)通信应用。这个程序允许用户之间直接进行实时聊天,无需通过中央服务器作为中介,因此具有较高的效率和隐私性。对于初学者...

    基于Java的源码-P2P-多用户在线聊天室(Java源码).zip

    这个基于Java的源码项目是一个P2P(Peer-to-Peer)多用户在线聊天室,它允许多个用户通过网络进行实时通信。在Java编程领域,这样的应用通常涉及到网络编程、多线程、对象序列化以及可能的GUI设计等多个重要知识点。...

    C#编写P2P视频聊天程序

    在本文中,我们将深入探讨如何使用C#编程语言来创建一个P2P(点对点)视频聊天程序。P2P技术允许用户直接通过互联网互相通信,而无需经过中心服务器,这大大降低了带宽需求和延迟,提高了通信效率。下面我们将详细...

Global site tag (gtag.js) - Google Analytics