仿扣扣聊天工具(实现多对一)

原创 2012年03月30日 09:23:58

通过线程处理来自客户端或者服务端的信息,实现了一对一以及多对一的效果,也就是服务端可以同时接收来自多方的客户端的信息,四个页面,分别是服务端的UI和Thread线程,还有客户端的UI和线程,服务端是本机~~~

/*

 * ServerUI.java
 *
 * Created on __DATE__, __TIME__
 */
package socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.DefaultListModel;

/**
 *
 * @author  __USER__
 */
public class ServerUI extends javax.swing.JFrame {


final DefaultListModel dlm = new DefaultListModel();
HashMap<String, ClientBean> clientMap = new HashMap<String, ClientBean>(); //clientBean里面包含client的所有基本信息
protected int i;


/** Creates new form ServerUI */
public ServerUI() {
initComponents();
startServer();


jListClient.setModel(dlm);

}
private String readName(Socket client){
//读取登陆状态的客户端的姓名
String name=null;

try {
BufferedReader br=new BufferedReader(new InputStreamReader(client.getInputStream(),"GBK"));
String line=br.readLine();
if(line!=null){
name=line;
}
Thread.sleep(1000);

} catch (InterruptedException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();

}
return name;

}
private void startServer() {
// 启动服务端,将登陆状态的客户端的信息显示在服务端的界面
Thread t = new Thread() {


public void run() {
try {
ServerSocket server = new ServerSocket(12345);
while (true) {
Socket client = server.accept();
String ip = new String(client.getInetAddress()
.getHostAddress()); //获取客户端登陆的Ip

String name=readName(client);


ClientBean clientBean = new ClientBean();
clientBean.setIp(ip);
clientBean.setName(name);
clientBean.setSocket(client);
clientMap.put(ip, clientBean);
dlm.addElement(clientBean);
ServerThread st = new ServerThread(client,
jTextAreaMsg1);
Thread t = new Thread(st);
t.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();


Thread heartBeat = new Thread() {
@Override
public void run() {
try {
//不断轮询查看客户端的连接状态,连接还是断开
while (true) {
Iterator<String> it = clientMap.keySet().iterator(); //key是String类型
while (it.hasNext()) { //it.hasNext是判断是否后面还有,如果有就继续运行下去,若没有记终止循环
String key = it.next(); //it.next是获取它的下一个数据,将其保存在key里,
ClientBean cb = clientMap.get(key);
try {
cb.getSocket().sendUrgentData(0XFF);


} catch (Exception e) {
//有异常,说明已经断开
System.out.println("客户端已断开");


//1、clientMap将断开的客户端移除掉
clientMap.remove(key);
//2、界面上也删除
for(int i=0;i<dlm.getSize();i++){
ClientBean clientBean=(ClientBean)dlm.getElementAt(i);
if(clientBean.getIp().equals(key)){
dlm.removeElement(clientBean);
}
}

}


}
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}


}
};
heartBeat.start();


}


/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
//GEN-BEGIN:initComponents
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {


jScrollPane1 = new javax.swing.JScrollPane();
jTextAreaMsg1 = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
jTextAreaMsg2 = new javax.swing.JTextArea();
jButtonSend = new javax.swing.JButton();
jScrollPane3 = new javax.swing.JScrollPane();
jListClient = new javax.swing.JList();


setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("\u670d\u52a1\u7aef");


jTextAreaMsg1.setBackground(new java.awt.Color(204, 255, 255));
jTextAreaMsg1.setColumns(20);
jTextAreaMsg1.setRows(5);
jScrollPane1.setViewportView(jTextAreaMsg1);


jTextAreaMsg2.setBackground(new java.awt.Color(204, 255, 255));
jTextAreaMsg2.setColumns(20);
jTextAreaMsg2.setRows(5);
jScrollPane2.setViewportView(jTextAreaMsg2);


jButtonSend.setBackground(new java.awt.Color(204, 255, 255));
jButtonSend.setFont(new java.awt.Font("隶书", 0, 18));
jButtonSend.setForeground(new java.awt.Color(255, 51, 255));
jButtonSend.setText("\u53d1\u9001");
jButtonSend.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonSendActionPerformed(evt);
}
});


jListClient.setBackground(new java.awt.Color(204, 255, 255));
jListClient.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "192.168.9.236", "192.168.9.235",
"192.168.9.234", "192.168.9.233", "192.168.9.237" };


public int getSize() {
return strings.length;
}


public Object getElementAt(int i) {
return strings[i];
}
});
jScrollPane3.setViewportView(jListClient);


javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
getContentPane());
getContentPane().setLayout(layout);
layout
.setHorizontalGroup(layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
layout
.createSequentialGroup()
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
layout
.createSequentialGroup()
.addComponent(
jScrollPane3,
javax.swing.GroupLayout.PREFERRED_SIZE,
108,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(
jScrollPane1,
javax.swing.GroupLayout.DEFAULT_SIZE,
346,
Short.MAX_VALUE)
.addComponent(
jScrollPane2,
javax.swing.GroupLayout.DEFAULT_SIZE,
346,
Short.MAX_VALUE)))
.addGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
layout
.createSequentialGroup()
.addContainerGap(
381,
Short.MAX_VALUE)
.addComponent(
jButtonSend,
javax.swing.GroupLayout.PREFERRED_SIZE,
81,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap()));
layout
.setVerticalGroup(layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
layout
.createSequentialGroup()
.addContainerGap()
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(
jScrollPane3,
javax.swing.GroupLayout.PREFERRED_SIZE,
285,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(
layout
.createSequentialGroup()
.addComponent(
jScrollPane1,
javax.swing.GroupLayout.PREFERRED_SIZE,
182,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(
jScrollPane2,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED,
45,
Short.MAX_VALUE)
.addComponent(
jButtonSend,
javax.swing.GroupLayout.PREFERRED_SIZE,
55,
javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap()));


pack();
}// </editor-fold>
//GEN-END:initComponents


private void jButtonSendActionPerformed(java.awt.event.ActionEvent evt) {
//向客户端发送消息
Object[] selectedClients = (Object[])jListClient.getSelectedValues();
for (Object object : selectedClients) {
try {
ClientBean clientBean=(ClientBean)object;
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientMap.get(clientBean.getIp()).getSocket().getOutputStream(), "GBK"));
bw.write(jTextAreaMsg2.getText() + "\n");
bw.flush();
          jTextAreaMsg2.setText(null);
} catch (UnsupportedEncodingException e) {

e.printStackTrace();
} catch (IOException e) {

e.printStackTrace();
}
}


}


/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerUI().setVisible(true);
}
});
}


//GEN-BEGIN:variables
// Variables declaration - do not modify
private javax.swing.JButton jButtonSend;
private javax.swing.JList jListClient;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JTextArea jTextAreaMsg1;
private javax.swing.JTextArea jTextAreaMsg2;
// End of variables declaration//GEN-END:variables


}



//serverThread用线程来处理来自客户端的信息

package socket;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketException;
import javax.swing.JTextArea;

public class ServerThread implements Runnable{
private Socket client=null;
private JTextArea msgList=null;
public ServerThread(Socket client,JTextArea msgList){
this.client=client;
this.msgList=msgList;

}
public void run(){
//获取客户端的信息
while(true){
try {
BufferedReader br=new BufferedReader(new InputStreamReader(client.getInputStream(),"GBK"));
try {
client.sendUrgentData(0XFF);
} catch (Exception e) {
break;
}
String line=br.readLine();
if(line!=null){
msgList.setText(msgList.getText()+line+"\n");
}
Thread.sleep(1000);
}catch(SocketException e){
break;

} catch (InterruptedException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();

}

}

}
}


/*
 * ClientUI.java
 *
 * Created on __DATE__, __TIME__
 */


package socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import javax.swing.JList;
import javax.swing.JOptionPane;


/**
 *
 * @author  __USER__
 */
public class ClientUI extends javax.swing.JFrame {
private Socket client = null;


/** Creates new form ClientUI */
public ClientUI() {
initComponents();
connectServer();
sendClientName();
startClientThread();
}


private void sendClientName() {
//将登陆上的用户的名字传给服务端
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
client.getOutputStream(), "GBK"));
bw.write("睢雨亭" + "\n");
bw.flush();
jTextAreaMsg4.setText(null);


} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}


}





private void startClientThread() {
// 启动客户端的线程
ClientThread ct = new ClientThread(client, jTextAreaMsg3);
Thread t = new Thread(ct);
t.start();
}


private void connectServer() {
// 连接服务端
try {
client = new Socket("192.168.9.236", 12345);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
//GEN-BEGIN:initComponents
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {


jScrollPane1 = new javax.swing.JScrollPane();
jTextAreaMsg3 = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
jTextAreaMsg4 = new javax.swing.JTextArea();
jButtonSend = new javax.swing.JButton();


setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("\u5ba2\u6237\u7aef");
setBackground(new java.awt.Color(255, 255, 255));

jTextAreaMsg3.setBackground(new java.awt.Color(204, 255, 255));
jTextAreaMsg3.setColumns(20);
jTextAreaMsg3.setRows(5);
jScrollPane1.setViewportView(jTextAreaMsg3);
jTextAreaMsg4.setBackground(new java.awt.Color(204, 255, 255));
jTextAreaMsg4.setColumns(20);
jTextAreaMsg4.setRows(5);
jScrollPane2.setViewportView(jTextAreaMsg4);
jButtonSend.setBackground(new java.awt.Color(204, 255, 255));
jButtonSend.setFont(new java.awt.Font("隶书", 0, 18));
jButtonSend.setForeground(new java.awt.Color(255, 0, 255));
jButtonSend.setText("\u53d1\u9001");
jButtonSend.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButtonSendActionPerformed(evt);
}
});


javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
getContentPane());
getContentPane().setLayout(layout);
layout
.setHorizontalGroup(layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
layout
.createSequentialGroup()
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
layout
.createSequentialGroup()
.addContainerGap()
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
false)
.addComponent(
jScrollPane2,
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(
jScrollPane1,
javax.swing.GroupLayout.Alignment.LEADING,
javax.swing.GroupLayout.DEFAULT_SIZE,
274,
Short.MAX_VALUE)))
.addGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
layout
.createSequentialGroup()
.addGap(
294,
294,
294)
.addComponent(
jButtonSend,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)))
.addContainerGap()));
layout.setVerticalGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap().addComponent(
jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE,
225, javax.swing.GroupLayout.PREFERRED_SIZE).addGap(18,
18, 18).addComponent(jScrollPane2,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE).addGap(18, 18,
18).addComponent(jButtonSend,
javax.swing.GroupLayout.PREFERRED_SIZE, 46,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)));


pack();
}// </editor-fold>
//GEN-END:initComponents


private void jButtonSendActionPerformed(java.awt.event.ActionEvent evt) {
//得到socket的输出流,并获取对应的信息
if (client == null) {
JOptionPane.showMessageDialog(this, "未成功连接服务器");
return;

}


//正确发送消息的情况
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
client.getOutputStream(), "GBK"));
bw.write(jTextAreaMsg4.getText() + "\n");
bw.flush();
jTextAreaMsg4.setText(null);


} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}


}


/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientUI().setVisible(true);
}
});
}


//GEN-BEGIN:variables
// Variables declaration - do not modify
private javax.swing.JButton jButtonSend;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextAreaMsg3;
private javax.swing.JTextArea jTextAreaMsg4;
// End of variables declaration//GEN-END:variables


}


package socket;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import javax.swing.JTextArea;


public class ClientThread implements Runnable{
private Socket socket=null;
private JTextArea msgList=null;

public ClientThread(Socket socket,JTextArea msgList){
this.socket=socket;
this.msgList=msgList;
}

@Override

public void run() {
//接收来自服务端的信息
while(true){
BufferedReader br=null;
String line=null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"GBK"));
line = br.readLine();
} catch (UnsupportedEncodingException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}

if(line!=null){
msgList.setText(msgList.getText()+line+"\n");
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}


}











  






仿QQ聊天程序(java)

仿QQ聊天程序 转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907 一、设计内容及要求 1.1综述 A.系统概述 我们要做的就是类...
  • zwx19921215
  • zwx19921215
  • 2014年03月17日 15:52
  • 83088

Android沉浸式状态栏之高仿QQApp

伴随着 Android 5.0 发布的 Material Design,让 Android 应用告别了以前的工程师审美,迎来了全新的界面,灵动的交互,也让越来越多的 App 开始遵从 material...
  • seven2729
  • seven2729
  • 2016年11月25日 15:17
  • 684

RecyclerView 左滑(仿QQ左滑删除)

一、效果图 二、实现步骤
  • Kate_sicheng
  • Kate_sicheng
  • 2017年08月26日 14:25
  • 903

QQ收到消息窗口闪烁效果实现[C#]

建个winForm程序加两个button,btnFlash和btnStopFlash,再加一个timer控件,代码如下,效果就出来了using System;using System.Collecti...
  • Sugar_Tiger
  • Sugar_Tiger
  • 2009年08月28日 10:26
  • 2495

仿QQ聊天工具(JAVA实现)项目总结

一、遇到的异常及解决办法 1.        org.hibernate.HibernateException:Could not parse configuration: /hibernate.c...
  • Cmainlove
  • Cmainlove
  • 2014年12月23日 09:00
  • 1860

Qt实现的局域网通信软件(仿QQ版本)

Qt5实现的局域网通信工具,支持公网。类似软件百度一大把,但是还是想整理一份属于自己的专属QQ。支持跨平台。...
  • nigoole
  • nigoole
  • 2017年07月03日 13:57
  • 1022

网络编程(三)---- MFC 仿QQ聊天软件

今天来八一八,MFC的SOCKET 编程,利用CSocket实现一个基于TCP实现一个QQ聊天程序。你会发现,MFC要比WIN32 简单的多。但是如果你不理解具体API socket基础知识,你可能会...
  • lh844386434
  • lh844386434
  • 2011年08月12日 00:50
  • 28723

仿QQ聊天软件及源码java版

一直以来,很多java的同志们都没有一个完整资料来参考。把源码贴出来,大家共享! import java.awt.BorderLayout; import java.awt.Component; i...
  • youyigong
  • youyigong
  • 2011年11月23日 17:59
  • 26947

使用RecyclerView 简单实现QQ好友列表展开效果

最近自己想捣鼓个社交类的app,所以想了解一下QQ列表的实现。对于这样的展开效果, 我们很容易想到使用ExpandableListView类,当然我也是,但是我在网上看到有人用 ListVie...
  • Henry__Mark
  • Henry__Mark
  • 2016年10月26日 20:50
  • 2683

【Android】 开发即时聊天工具 YQ (仿QQ) 教程:目录

Android 开发即时聊天工具 YQ (仿QQ)  开发环境: Eclipse 4.2 JDK 1.7  Android SDK 2.2 服务器端不能运行的请检查你的J...
  • Vestigge
  • Vestigge
  • 2013年08月12日 11:09
  • 8553
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:仿扣扣聊天工具(实现多对一)
举报原因:
原因补充:

(最多只允许输入30个字)