Socket编程------模拟QQ聊天(TCP)
来源:互联网 发布:铁岭网络预约出租汽车 编辑:程序博客网 时间:2024/05/16 09:03
模拟QQ聊天
一、要求
1、一个服务器可以与多个用户同时通讯
2、用户可以通过服务器与用户之间通讯
3、用户可以选择和所有人发消息,也可以选择和某个用户单独发消息
4、服务器要显示当前所有在线人员
5、用户要显示当前在线的人员
6、当有新用户登录时或在线用户退出时,服务器要向所有其他在线用户发送提示信息,并且服务器也要显示相应的提示信息
7、不能有相同的用户名同时登陆
8、不能发送空消息
9、客户端可以设置连接的服务器IP和端口
在服务器端 用一个HashMap<userName,socket> 维护所有用户相关的信息,从而能够保证和所有的用户进行通讯。
客户端的动作:
(1)连接(登录):发送userName 服务器的对应动作:1)界面显示,2)通知其他用户关于你登录的信息, 3)把其他在线用户的userName通知当前用户 4)开启一个线程专门为当前线程服务
(2)退出(注销):
(3)发送消息
※※发送通讯内容之后,对方如何知道是干什么,通过消息协议来实现:
客户端向服务器发的消息格式设计:
命令关键字@#接收方@#消息内容@#发送方
1)连接:userName ----握手的线程serverSocket专门接收该消息,其它的由服务器新开的与客户进行通讯的socket来接收
2)退出:exit@#全部@#null@#userName
3)发送: on @# JList.getSelectedValue() @# tfdMsg.getText() @# tfdUserName.getText()
服务器向客户端发的消息格式设计:
命令关键字@#发送方@#消息内容
登录:
1) msg @#server @# 用户[userName]登录了 (给客户端显示用的)
2) cmdAdd@#server @# userName (给客户端维护在线用户列表用的)
退出:
1) msg @#server @# 用户[userName]退出了 (给客户端显示用的)
2) cmdRed@#server @# userName (给客户端维护在线用户列表用的)
发送:
msg @#消息发送者( msgs[3] ) @# 消息内容 (msgs[2])
三、代码
ClientForm.java
package cn.hncu;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.IOException;import java.io.PrintWriter;import java.net.Socket;import java.util.Scanner;import javax.swing.DefaultListModel;import javax.swing.JButton;import javax.swing.JDialog;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JList;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.ListSelectionModel;import javax.swing.border.TitledBorder;public class ClientForm extends JFrame implements ActionListener{private JTextField tfdUserName=null;private JTextArea allMsg=null;private DefaultListModel dlm=null;private JList list=null;private JTextField tfdMsg=null;private static PrintWriter pw;private static String HOST="192.168.1.106";private static int PORT=9090;private static Socket clientSocket=null;public ClientForm(){//menuaddMenu();//panel aboveJPanel p1=new JPanel();p1.add(new JLabel("userLogo"));tfdUserName=new JTextField(10);p1.add(tfdUserName);JButton connect=new JButton("connect");connect.setActionCommand("connect");connect.addActionListener(this);JButton exit=new JButton("exit");exit.setActionCommand("exit");exit.addActionListener(this);p1.add(connect);p1.add(exit);this.getContentPane().add(p1,BorderLayout.NORTH);//middle panelJPanel p2=new JPanel(new BorderLayout());this.getContentPane().add(p2,BorderLayout.CENTER);//online list widgetdlm=new DefaultListModel();dlm.addElement("ALL");list=new JList(dlm);list.setSelectedIndex(0);list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);list.setVisibleRowCount(2);JScrollPane js=new JScrollPane(list);js.setBorder(new TitledBorder("Online"));js.setPreferredSize(new Dimension(70, p2.getHeight()));p2.add(js,BorderLayout.EAST);//chatting message areaallMsg=new JTextArea();allMsg.setEditable(false);p2.add(new JScrollPane(allMsg),BorderLayout.CENTER);//message sending panelJPanel p3=new JPanel();JLabel messageLabel=new JLabel("message");p3.add(messageLabel);tfdMsg=new JTextField(20);p3.add(tfdMsg);JButton sendBtn=new JButton("send");sendBtn.setActionCommand("send");sendBtn.addActionListener(this);p3.add(sendBtn);this.getContentPane().add(p3,BorderLayout.SOUTH);this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {sendExitMsg();}});this.setBounds(300, 300, 400, 300);this.setVisible(true);}private void addMenu() {JMenuBar menubar=new JMenuBar();this.setJMenuBar(menubar);JMenu menu=new JMenu("Selection");menubar.add(menu);JMenuItem itemSet=new JMenuItem("Set");JMenuItem itemHelp=new JMenuItem("Help");menu.add(itemSet);menu.add(itemHelp);itemSet.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {final JDialog dlg=new JDialog(ClientForm.this);dlg.setLayout(new FlowLayout());dlg.setBounds(ClientForm.this.getX()+40, ClientForm.this.getY()+40, 300, 100);dlg.add(new JLabel("server"));final JTextField tfdId=new JTextField(HOST);final JTextField tfdPort=new JTextField(""+PORT);dlg.add(tfdId);dlg.add(new JLabel(":"));dlg.add(tfdPort);JButton btnSet=new JButton("Set");dlg.add(btnSet);btnSet.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {HOST=tfdId.getText();PORT=Integer.parseInt(tfdPort.getText());dlg.dispose();}});dlg.setVisible(true);}});itemHelp.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {JDialog dlg=new JDialog(ClientForm.this);dlg.setLayout(new FlowLayout());dlg.setBounds(ClientForm.this.getX()+40, ClientForm.this.getY()+40, 300, 100);dlg.add(new JLabel("Copyright@hncu.2016-5-15,QQ:666666"));dlg.setVisible(true);}});}@Overridepublic void actionPerformed(ActionEvent e) {if (e.getActionCommand().equalsIgnoreCase("connect")){System.out.println("connecting server");String userName=tfdUserName.getText().trim();byte byteName[]=userName.getBytes();if (byteName.length==0){JOptionPane.showMessageDialog(this, "please input right name format");return;} else {try {connecting(userName);} catch (Exception e1) {JOptionPane.showMessageDialog(this, "Failed in connecting,please check your internet or ip address and port");return;}((JButton)e.getSource()).setEnabled(false);tfdUserName.setEditable(false);}}if (e.getActionCommand().equalsIgnoreCase("send")){if (tfdMsg.getText()==null){JOptionPane.showMessageDialog(this, "Please input dialog message");return;}String str="on@#"+list.getSelectedValue()+"@#"+tfdMsg.getText()+"@#"+tfdUserName.getText();try {pw.println(str);pw.flush();} catch (Exception e1) {JOptionPane.showMessageDialog(this, "Please connect the server first.");return;}tfdMsg.setText("");}if (e.getActionCommand().equalsIgnoreCase("exit")){sendExitMsg();}}private void sendExitMsg() {if (clientSocket==null){System.exit(0);}String str="exit@#all@#null@#"+tfdUserName.getText();pw.println(str);pw.flush();System.exit(0);}private void connecting(String userName) throws Exception{clientSocket=new Socket(HOST,PORT);if (userName!=""){pw=new PrintWriter(clientSocket.getOutputStream(),true);pw.println(userName);this.setTitle("User ["+userName+"] is online...");new ClientThread().start();}}class ClientThread extends Thread{@Overridepublic void run() {try {Scanner input=new Scanner(clientSocket.getInputStream());while (input.hasNextLine()){String str=input.nextLine();String msgs[]=str.split("@#");if ("msg".equals(msgs[0])){if ("server".equals(msgs[1])){str="[notify]:"+msgs[2];} else{str="["+msgs[1]+"] says:"+msgs[2];}allMsg.append("\r\n"+str);} else if ("cmdAdd".equals(msgs[0])){dlm.addElement(msgs[2]);} else if ("cmdRed".equalsIgnoreCase(msgs[0])){dlm.removeElement(msgs[2]);}}} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {JFrame.setDefaultLookAndFeelDecorated(true);new ClientForm();}}ServerForm.java
package cn.hncu;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.Toolkit;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.io.IOException;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Scanner;import javax.swing.DefaultListModel;import javax.swing.JFrame;import javax.swing.JList;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.KeyStroke;import javax.swing.border.TitledBorder;public class ServerForm extends JFrame {private static final int PORT=9090;private JTextArea area;private DefaultListModel dlm;private Map<String, Socket> map=new HashMap<String, Socket>();public ServerForm() {this.setDefaultCloseOperation(EXIT_ON_CLOSE);final int winWidth=(int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();final int winHeight=(int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();//message windowarea=new JTextArea();area.setEditable(false);this.getContentPane().add(new JScrollPane(area),BorderLayout.CENTER);//online list widgetdlm=new DefaultListModel();JList list=new JList(dlm);JScrollPane js=new JScrollPane(list);js.setBorder(new TitledBorder("Online"));js.setPreferredSize(new Dimension(100, this.getHeight()));this.getContentPane().add(js,BorderLayout.EAST);//menuJMenuBar bar=new JMenuBar();this.setJMenuBar(bar);JMenu menu=new JMenu("Control(C)");bar.add(menu);menu.setMnemonic('C');final JMenuItem run=new JMenuItem("run");run.setActionCommand("run");run.setAccelerator(KeyStroke.getKeyStroke('R',KeyEvent.CTRL_MASK));menu.add(run);menu.addSeparator();final JMenuItem exit=new JMenuItem("exit");exit.setActionCommand("exit");exit.setAccelerator(KeyStroke.getKeyStroke('E',KeyEvent.CTRL_MASK));menu.add(exit);ActionListener al=new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (e.getActionCommand().equalsIgnoreCase("run")){startServer();run.setEnabled(false);} else {System.exit(0);}}};run.addActionListener(al);exit.addActionListener(al);this.setBounds(winWidth/4, winHeight/4, winWidth/2, winHeight/2);this.setVisible(true);}private void startServer() {try {ServerSocket server=new ServerSocket(PORT);area.append("start service:"+server);new ServerThread(server).start();} catch (IOException e) {e.printStackTrace();}}class ServerThread extends Thread{private ServerSocket server=null;ServerThread(ServerSocket server){this.server=server;}@Overridepublic void run() {try {while (true){Socket clientSocket=server.accept();Scanner input=new Scanner(clientSocket.getInputStream());if (input.hasNextLine()){String userName=input.nextLine();area.append("\r\n user:["+userName+"] login,"+clientSocket);dlm.addElement(userName);new ClientThread(clientSocket).start();msgAll(userName);msgSelf(clientSocket);map.put(userName, clientSocket);}}} catch (IOException e) {e.printStackTrace();}}}class ClientThread extends Thread{private Socket clientSocket=null;public ClientThread(Socket clientSocket) {this.clientSocket = clientSocket;}@Overridepublic void run() {try {Scanner input=new Scanner(clientSocket.getInputStream());while (input.hasNextLine()){String str=input.nextLine();String msgs[]=str.split("@#");if (msgs.length!=4){JOptionPane.showMessageDialog(null, "wrong message format");}if ("on".equalsIgnoreCase(msgs[0])){sendMsgToSb(msgs);}if ("exit".equalsIgnoreCase(msgs[0])){map.remove(msgs[3]);dlm.removeElement(msgs[3]);sendExitMsgToAll(msgs);area.append("\r\n user["+msgs[3]+"] leaves.");}}} catch (IOException e) {e.printStackTrace();}}}private void sendExitMsgToAll(String msgs[]) throws IOException {Iterator<String> it=map.keySet().iterator();while (it.hasNext()){String userName=it.next();Socket s=map.get(userName);PrintWriter pw=new PrintWriter(s.getOutputStream(), true);String msg="msg@#server@#user ["+msgs[3]+"] leaves";pw.println(msg);msg="cmdRed@#server@#"+msgs[3];pw.println(msg);pw.flush();}}private void sendMsgToSb(String[] msgs) throws IOException {if ("all".equalsIgnoreCase(msgs[1])){Iterator<String> userNames=map.keySet().iterator();while (userNames.hasNext()){String userName=userNames.next();Socket s=map.get(userName);String msg="msg@#"+msgs[3]+"@#"+msgs[2];PrintWriter pw=new PrintWriter(s.getOutputStream(), true);pw.println(msg);pw.flush();}} else {String userName=msgs[1];Socket s=map.get(userName);String msg="msg@#"+msgs[3]+"@#"+msgs[2];PrintWriter pw=new PrintWriter(s.getOutputStream(), true);pw.println(msg);pw.flush();}}private void msgAll(String userName) {Iterator<Socket> it = map.values().iterator();while(it.hasNext()){Socket s = it.next();try {PrintWriter pw = new PrintWriter(s.getOutputStream(), true);String msg = "msg@#server@#用户["+userName+"]登录了.";pw.println(msg);pw.flush();msg = "cmdAdd@#server@#"+userName;pw.println(msg);pw.flush();} catch (IOException e) {e.printStackTrace();}}}private void msgSelf(Socket clientSocket) {try {PrintWriter pw=new PrintWriter(clientSocket.getOutputStream(),true);Iterator<String> it=map.keySet().iterator();while (it.hasNext()){String msg="cmdAdd@#server@#"+it.next();pw.println(msg);pw.flush();}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {JFrame.setDefaultLookAndFeelDecorated(true);new ServerForm();}}
本程序修复好的漏洞:
没有输入用户名应不可登录
登陆后应不可再次点击登录按钮
没有登录应不可发送消息且发送的消息不可为空
IP地址和端口错误也不可登录
- Socket编程------模拟QQ聊天(TCP)
- 模拟QQ(Socket编程)
- 黑马程序员 java IO TCP Socket ServerSocket Thread Runnable 模拟qq聊天
- Socket编程 ------ 模拟QQ聊天工具
- socket 编程 TCP 实现简单聊天功能
- 简单模拟qq聊天程序(TCP版)
- 模拟QQ聊天窗口
- 【java编程】Socket编程之UDP模拟简单聊天功能
- 模拟QQ聊天程序_服务器端_网络编程
- 模拟QQ聊天程序_客户端_网络编程
- Socket编程(三)---仿QQ多人聊天实例
- 多线程tcp聊天模拟
- Socket TCP聊天通讯
- java网络编程一:Socket用法,简单模拟一对一聊天
- java网络编程一:Socket用法,简单模拟一对一聊天
- java网络编程一:Socket用法,简单模拟一对一聊天
- java网络编程一:Socket用法,简单模拟一对一聊天
- java网络编程一:模拟qq聊天功能,实现一对一聊天
- iOS: 使用CGContextRef,CGPath和UIBezierPath来绘画
- 二分查找算法
- 惊心动魄-微信抢红包传播活动
- 删除list中元素
- 1.C++--关于文件间共享代码的方法
- Socket编程------模拟QQ聊天(TCP)
- POJ 1066 Treasure Hunt(转化线段相交)
- Android Animation动画(Frame-By-Frame Animations 、Tween Animations 、Property Animation)的详解
- mantis配置笔记
- 系统优化
- Liunx 安装JDK
- POJ2947 Widget Factory(高斯消元模板题)
- 2016SDAU编程练习三1018
- [视图]上面带描边的圆角,底部不描边的直角 按键xml 去局部描边