Socket编程 ------ 模拟QQ聊天工具

模拟QQ聊天


一、要求

1、一个服务器可以与多个用户同时通讯

2、用户可以通过服务器与用户之间通讯

3、用户可以选择和所有人发消息,也可以选择和某个用户单独发消息

4、服务器要显示当前所有在线人员

5、用户要显示当前在线的人员

6、当有新用户登录时或在线用户退出时,服务器要向所有其他在线用户发送提示信息,并且服务器也要显示相应的提示信息

7、不能有相同的用户名同时登陆

8、不能发送空消息

9、客户端可以设置连接的服务器IP和端口


二、了解B/S模式的底层socket通讯原理

QQ聊天可以利用协议方式发送消息。所以先要了解浏览器和服务器直接的协议,从而仿照。

浏览器的请求

GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 192.168.31.169:9090
DNT: 1
Connection: Keep-Alive


请求行,包含:  请求方式(GET或POST) 空格 请求的资源路径 空格 http的协议版本
接下来是请求消息头(...)
空行
请求体(包括浏览器向服务器提交的表单数据等)

HTTP/1.1 200 OK
Date: Fri, 11 Sep 2015 12:33:43 GMT
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Set-Cookie: JSESSIONID=409C8CF8220AD78D26D47B15DCEADCD3; Path=/; HttpOnly
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
Content-Language: zh-CN

应答行,包含:http协议版本 空格 应答状态码 空格 应答状态码信息码描述
应答消息头(...)
空行
应答体(页面内容)

三、QQ聊天协议

在服务器端 用一个HashMap<userName,socket> 维护所有用户相关的信息,从而能够保证和所有的用户进行通讯。

客户端的动作:

(1)连接(登录):发送userName    服务器的对应动作:1)界面显示,2)通知其他用户关于你登录的信息, 3)把其他在线用户的userName通知当前用户 4)开启一个线程专门为当前线程

服务

(2)退出(注销):

(3)发送消息

※※发送通讯内容之后,对方如何知道是干什么,通过消息协议来实现:


客户端向服务器发的消息格式设计:
命令关键字@#接收方@#消息内容@#发送方
连接:userName      ----握手的线程serverSocket专门接收该消息,其它的由服务器新开的与客户进行通讯的socket来接收
退出:exit@#全部@#null@#userName
发送: 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 com.sina.chat;

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.net.UnknownHostException;
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 userName;//用户名
	private DefaultListModel lm;//用于维护在线用户列表
	private JList list;
	private JTextField msg;//发送消息口
	private JTextArea allMsg;
	private JButton btnConn;
	
	private String HOST="127.0.0.1";//服务器地址
	private int PORT = 9090;//服务器端口号


	public ClientForm(){
		addJMnuBar();//添加并处理自定义菜单
		JPanel upP = new JPanel();
		upP.add(new JLabel("用户标识"));
		userName = new JTextField(10);
		upP.add(userName);
		
		//上部面板
		btnConn = new JButton("连接");
		btnConn.setActionCommand("conn");
		btnConn.addActionListener(this);
		upP.add(btnConn);
		JButton btnExit = new JButton("退出");
		btnExit.setActionCommand("exit");
		btnExit.addActionListener(this);
		upP.add(b
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值