`
ggxin
  • 浏览: 42512 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

Java写的P2P聊天程序

阅读更多

这几天偶然想研究下P2P通信的原理,于是就用Java写了一个,测试可以通过,但是在不同的运营商之间却有点问题,比如联通跟电信之间可能出现不通现象,不知是不是被卡杀了。

客户端:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Client extends Thread implements ActionListener{
	//是否停止
	public static int STOP=0;
	
	//在线用户列表
	public static Map<String,SocketAddress> userMap=new HashMap();
	
	private DatagramSocket client;
	
	private JFrame frame;
	//聊天信息
	private JTextArea info;
	//在线用户
	private JTextArea onlineUser;
	private JTextField msgText;
	
	private JButton sendButton;
	
	public Client(DatagramSocket client)throws Exception
	{

		this.client=client;
		this.frame=new JFrame("P2P聊天");
		frame.setSize(800, 400);
		
		sendButton=new JButton("发送");
		JScrollBar scroll=new JScrollBar();
		this.info=new JTextArea(10,30);
		//激活自动换行功能 
		info.setLineWrap(true);
		info.setWrapStyleWord(true);
		info.setEditable(false);
		scroll.add(info);
		
		onlineUser=new JTextArea(10,30);
		onlineUser.setLineWrap(true);
		onlineUser.setWrapStyleWord(true);
		onlineUser.setEditable(false);
		
		
		JPanel infopanel=new JPanel();
		infopanel.add(info,BorderLayout.WEST);
		JPanel infopanel1=new JPanel();
		JLabel label=new JLabel("在线用户");
		infopanel1.add(label, BorderLayout.NORTH);
		infopanel1.add(onlineUser, BorderLayout.SOUTH);
		infopanel.add(infopanel1,BorderLayout.EAST);

		JPanel panel=new JPanel();
		
		msgText=new JTextField(30);
	
		panel.add(msgText);
		panel.add(sendButton);
		frame.add(infopanel,BorderLayout.NORTH);
		frame.add(panel,BorderLayout.SOUTH);
		frame.setVisible(true);
		
		sendButton.addActionListener(this);
		
		frame.addWindowListener(new   WindowAdapter(){ 
            public   void   windowClosing(WindowEvent   e){ 
                System.exit(0);
            } 
         }); 
		

	}
	
	/**
	 * 给其他在线用户发送心跳 保持session有效
	 */
	private void sendSkip()
	{
		new Thread(){
			public void run()
			{
				try
				{
					String msg="skip";
					while(true)
					{
						if(STOP==1)
							break;
						if(userMap.size()>0)
						{
							 for (Entry<String, SocketAddress> entry : userMap.entrySet()) {
								 DatagramPacket data=new DatagramPacket(msg.getBytes(),msg.getBytes().length,entry.getValue());
								client.send(data);
							}
						}
						//每10s发送一次心跳
						Thread.sleep(10*1000);
					}
				}catch(Exception e){}
				
			}
		}.start();
	}
	
	//主要任务是接收数据
	//可以是其他用户发来的信息,也可以是服务器发来的在线用户数据
	public void run()
	{
		try
		{
			
			String msg;
			DatagramPacket data;
			
			//执行心跳
			sendSkip();
			
			while(true)
			{
				if(STOP==1)
					break;
				byte[] buf=new byte[1024];
				DatagramPacket packet = new DatagramPacket(buf, buf.length);
				client.receive(packet);
				msg=new String(packet.getData(),0,packet.getLength());
				if(msg.length()>0)
				{
					if(msg.indexOf("server:")>-1)
					{
						//服务器数据 格式server:ID#IP:PORT,。。
						String userdata=msg.substring(msg.indexOf(":")+1,msg.length());
						String[] user=userdata.split(",");
						for(String u:user)
						{
							if(u!=null&&u.length()>0)
							{
								String[] udata=u.split("#");
								String ip=udata[1].split(":")[0];
								int port=Integer.parseInt(udata[1].split(":")[1]);
								
								ip=ip.substring(1,ip.length());
								
								SocketAddress adds=new InetSocketAddress(ip,port);
								userMap.put(udata[0], adds);
								//给对方打洞 发送空白报文
								data=new DatagramPacket(new byte[0],0,adds);
								client.send(data);
								
							}
							
						}
						//更新在线用户列表
						this.onlineUser.setText("");
						for (Map.Entry<String, SocketAddress> entry : userMap.entrySet()) {
							this.onlineUser.append("用户"+entry.getKey()+"("+entry.getValue()+")\n");
						}

					}
					else if(msg.indexOf("skip")>-1);
					else
					{
						//普通消息
						this.info.append(packet.getAddress().toString()+packet.getPort()+" 说:"+msg);
						this.info.append("\n");
					}
				}
			}
		}
		catch(Exception e){}
	}
	
	public static void main(String args[])throws Exception
	{
		
		String serverIP="122.225.99.40";///122.225.99.40
		int port=6636;
		
		//构造一个目标地址
		SocketAddress target = new InetSocketAddress(serverIP, port); 
		
		DatagramSocket client = new DatagramSocket();
		String msg="向服务器报告!";
		byte[] buf=msg.getBytes();
		//向服务器发送上线数据
		DatagramPacket packet=new DatagramPacket(buf,buf.length,target);
		client.send(packet);
		new Client(client).start();
		
	}

	
	//按钮事件
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==this.sendButton)
		{
			try{
				String msg=this.msgText.getText();
				if(msg.length()>0)
				{
					this.info.append("我说:"+msg);
					this.info.append("\n");
					for (Map.Entry<String, SocketAddress> entry : userMap.entrySet()) {
						DatagramPacket data=new DatagramPacket(msg.getBytes(),msg.getBytes().length,entry.getValue());
						client.send(data);
					}
					
					this.msgText.setText("");
				}
			}
			catch(Exception ee){}
		}
		
	}
}

 服务器端:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务端
 * @author ggxin
 *
 */
public class Server extends Thread{
	//存储所有的用户IP与端口
	public static List<Map> userList=new ArrayList<Map>();
	//在线用户IP
	public static Map users=new HashMap();
	
	public static int index=1;
	
	private DatagramSocket server;
	
	public Server(DatagramSocket server)
	{
		this.server=server;
	}
	//线程负责给在线用户发送当前所有在线用户的信息
	public void run()
	{
		try
		{
			DatagramPacket sendPacket;
			StringBuffer msg;
			while(true)
			{
				for(Map user:Server.userList)
				{
					//服务器数据,标记server:
					msg=new StringBuffer("server:");
					for(Map map:Server.userList)
					{
						if(!map.get("id").toString().equals(user.get("id").toString()))
						{
							msg.append(map.get("id")+"#"+map.get("ip")+":"+map.get("port"));
							msg.append(",");
						}
					}
					if(!msg.toString().equals("server:"))
					{
						byte[] data=msg.toString().getBytes();
						//构造发送报文
						sendPacket = new DatagramPacket(data, data.length, (InetAddress)user.get("ip"), (Integer)user.get("port"));  
						server.send(sendPacket);
					}
				}
				Thread.sleep(2000);
				
			}
		}catch(Exception e){}
	}
	
	
	public static void main(String args[])throws Exception
	{

		int port=6636;
		
		//创建一个UDPsocket
		DatagramSocket server = new DatagramSocket(port);
	    byte[] buf = new byte[1024];  
	    //接收数据的udp包
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
       
        //开启服务
        new Server(server).start();

        String msg;
        //循环接收数据
        while(true)
        {
        	
        	server.receive(packet);
        	
        	msg=new String(packet.getData(),0,packet.getLength());
        	
        	if(msg!=null&&msg.equals("bye"))
        		break;
        	
        	if(msg.length()>0)
        	{
        		System.out.println("收到数据来自:("+packet.getAddress()+":"+packet.getPort()+")="+msg);
        		if(!users.containsKey(packet.getAddress()+":"+packet.getPort()))
        		{
        			Map map=new HashMap();
            		map.put("id", index);
            		map.put("ip", packet.getAddress());
            		map.put("port", packet.getPort());
            		userList.add(map);
            		
            		users.put(packet.getAddress()+":"+packet.getPort(), index);
            		index++;
        		}
        		
        	}
        }
        server.close();
	}

}

 

0
5
分享到:
评论
3 楼 ggxin 2013-04-16  
内部对于p2p似乎用途不是很大~
2 楼 wzjin 2013-04-16  
osacar 写道
我也正想写一个来内部用呢。

内部可以用飞鸽传书,也有java版的。
1 楼 osacar 2013-04-16  
我也正想写一个来内部用呢。

相关推荐

    基于java的p2p聊天程序

    【Java P2P聊天程序详解】 Java是一种广泛使用的编程语言,尤其在开发网络应用程序时,其强大的类库和跨平台特性使其成为首选。基于Java的P2P(peer-to-peer)聊天程序是一种允许用户直接相互通信,而无需通过中心...

    P2P聊天程序(JAVA)

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

    JAVA P2P聊天程序

    【JAVA P2P聊天程序】是一个基于Java编程语言实现的简单聊天应用,它利用了TCP协议进行通信,展示了如何在对等网络模式下进行数据交换。这个程序特别适合初学者,帮助他们理解如何使用Socket编程来创建网络连接,...

    基于java socket的P2P聊天程序

    在这个“基于java socket的P2P聊天程序”项目中,我们主要会涉及到以下关键知识点: 1. **Socket概念**:Socket是网络上的进程间通信(IPC)的一种方式,它允许两台机器相互通信。在Java中,`java.net.Socket`类和`...

    java聊天程序 p2p聊天程序

    在"java聊天程序"这个压缩包中,你应该能找到实现上述功能的源代码文件,通过阅读和运行这些代码,你可以深入理解Java P2P聊天程序的设计与实现。对于初学者来说,这是一个很好的实践项目,有助于巩固Java基础知识,...

    java实现的P2P即时聊天程序

    Java实现的P2P即时聊天程序是一个基于网络通信技术的软件应用,主要用于提供实时的、点对点的以及多人互动的聊天功能。在本项目中,我们主要关注以下几个核心知识点: 1. **Java网络编程**:Java提供了丰富的API...

    java UDP实现P2P聊天程序

    java实现P2P聊天程序,使用UDP协议。 含有GUI,带有注释。 若有不足,欢迎指正。

    java p2p 聊天软件

    Java P2P聊天软件是一种基于Socket编程实现的对等网络通信应用。在本文中,我们将深入探讨Java语言、P2P技术以及Socket编程在构建聊天软件中的应用。 首先,Java是一种广泛使用的面向对象的编程语言,它具有跨平台...

    用java做的p2p聊天软件

    【标题】"用Java做的P2P聊天软件"揭示了这个项目的核心技术栈,即Java编程语言,以及它实现的是一个点对点(P2P)的通信模式。点对点网络是一种分布式网络架构,其中每个节点(在这里是聊天客户端)都可以作为服务...

    Java P2P聊天程序(附带文档)

    【Java P2P聊天程序详解】 本项目是一个基于Java实现的P2P(Peer-to-Peer)聊天程序,主要用于教学目的,展示了在分布式系统中如何构建一个简单的通信平台。在这个程序中,我们将深入探讨以下几个核心知识点: 1. ...

    TT.rar_p2p socket java_p2p聊天

    在Java中实现P2P聊天程序,主要涉及以下几个关键点: 1. **Socket编程**:Socket是网络通信的基本组件,它提供了应用程序间的通信端点。在Java中,`java.net.Socket` 和 `java.net.ServerSocket` 类用于创建客户端...

    Java模拟QQ的P2P聊天

    总的来说,这个项目是一个实践性的学习案例,通过实现一个简单的P2P聊天应用,展示了Java Swing在UI设计上的能力,多线程在并发处理中的重要性,以及Socket和UDP在实时网络通信中的应用。对于想要深入理解Java网络...

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

    在本文中,我们将深入探讨如何...通过分析这些代码,我们可以进一步理解P2P聊天系统的具体实现细节。在实际开发中,可以在此基础上扩展功能,例如添加文件传输、语音聊天、用户认证等,以构建更完善的P2P即时通讯平台。

    java实现p2p通信

    ### Java实现P2P通信的关键知识点 #### 一、P2P通信模型及关键技术分析 ##### (一)信息的传递 **1. P2P通信模型** P2P(Peer-to-Peer)通信模型是一种分布式网络架构,其中的每一个节点既是服务的提供者也是...

    JAVA即时通讯+P2P+socket

    本项目利用Java的Socket编程技术,实现了一个简单的类QQ即时通讯程序,旨在提供基本的聊天功能。下面我们将深入探讨相关知识点。 首先,Java Socket编程是Java网络编程的基础,它提供了在网络之间两台计算机进行...

    JAVA的综合加解密聊天程序,附带文档

    利用RSA算法的公私密钥对DES算法的密钥进行加解密,对称DES密钥用来对聊天消息进行加解密,SHA算法用来对传输的数据进行数据校验。Java本版的机遇socket的聊天程序,课程学习资料和作业。附带详细代码说明文档。

    Java P2P聊天服务端源码

    Java P2P聊天服务端源码,通过NAT打洞技术,借助P2P服务端,采用客户端程序可以实现客户端点对点通讯

    java-p2p-chat:java p2p 聊天

    #自述##概述这是一个简单的P2P聊天项目。 主要是为了演示简单的P2P概念,但不包括分布式网络概念(你应该通过谷歌和维基百科改进自己)。 ##例子这是一个eclipse项目,你可以将它导入到eclipse中,然后导航到...

Global site tag (gtag.js) - Google Analytics