实现分析、

1.开启服务端

客户端选择‘登录以后’后,提示输入用户名和密码,验证成功则进入好友列表界面

2.用户聊天

双击好友,进入好友聊天界面。在信息框编辑信息 点击发送

当客户端向服务端发送数据时  根据指令的不同来处理不同的业务。

如果是登录,服务端向数据库查询用户信息。然后把处理后的信息发送给服务端。

如果是聊天业务,首先判断当前好友是否在线

如果好友不在线,处理后的信息发送给发送者,如果好友在线 处理后的信息发送给接收者(朋友)

服务端界面:

简单介绍一下 服务端的运行流程

当点击开启服务后 新建一个线程开启服务器循环监听客户端的连接

try {ServerSocket ss = new ServerSocket(4096);Socket socket = null;// 循环监听客户端的连接 每连接一个客户端 就为其实例化一个线程// 在该线程 I/O阻塞监听客户端发送的信息 不然你只能收到一次信息~while (true) {socket = ss.accept();ServiceThread thread = new ServiceThread(socket);thread.start();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}

至于为何要新建线程开启服务,归结于while循环里面的ss.accept();  如果一直没接收到客户端的连接,会导致线程阻塞。

如果你使用的还是main线程,那么关闭服务会无法点击。

而为了实现多客户端的连接  所以在上面我们为每一个客户端都开启一个线程。

线程的run方法为

 @Overridepublic void run() {ObjectInputStream ois = null;ObjectOutputStream oos = null;// 时刻监听 客户端发送来的数据while (socket != null) {try {ois = new ObjectInputStream(socket.getInputStream());CommandTranser msg = (CommandTranser) ois.readObject();// 处理客户端发送来的信息msg = execute(msg);if ("message".equals(msg.getCmd())) {/** 如果 msg.ifFlag即 服务器处理成功 可以向朋友发送信息 如果服务器处理信息失败 信息发送给发送者本人*/if (msg.isFlag()) {oos = new ObjectOutputStream(SocketList.getSocket(msg.getReceiver()).getOutputStream());} else {oos = new ObjectOutputStream(socket.getOutputStream());}}// 如果是登录请求 发送给发送者本人if ("login".equals(msg.getCmd())) {oos = new ObjectOutputStream(socket.getOutputStream());}oos.writeObject(msg);} catch (IOException e) {socket = null;} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

也是一个while循环  I/O阻塞接收客户端的信息。因为你不能只接收客户端一次的信息吧

如果你发现你只能接受一次信息  问题就出在这里了   因为我也在这里错了~~~~~~
在这里出现了CommandTranser类,execute(CommandTranser msg)方法和SocketList类里面的静态方法getSocket

SocketList类很简单  主要是保存已经和服务器成功连接的客户端

package cn.edu.xynu.util;import java.net.Socket;
import java.util.HashMap;import cn.edu.xynu.entity.SocketThread;/*** @author scx*  所有已经成功登录服务器的socket和昵称*/
public class SocketList {private static HashMap<String, Socket> map=new HashMap<String, Socket>();//将SocketThread入集合public static void addSocket(SocketThread socketThread){map.put(socketThread.getName(), socketThread.getSocket());}//通过昵称返回socketpublic static Socket getSocket(String name){return map.get(name);}
}

SocketThread实体类

所有成功连接客户端的socket实体类 包括一个socket (客户端)和昵称

package cn.edu.xynu.entity;import java.net.Socket;/*** @author scx 所有成功连接客户端的socket实体类 包括一个socket 一个昵称*/
public class SocketThread {private Socket socket;private String name;public SocketThread() {super();// TODO Auto-generated constructor stub}public SocketThread(Socket socket, String name) {super();this.socket = socket;this.name = name;}public Socket getSocket() {return socket;}public void setSocket(Socket socket) {this.socket = socket;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

CommandTranser这个类主要负责服务端和客户端的通信数据。

具体代码及注释如下:

package cn.edu.xynu.util;import java.io.Serializable;/*** @author scx*  客户端与服务器交互的数据*/
public class CommandTranser implements Serializable{private static final long serialVersionUID = 1L;private String sender=null;//发送者private String receiver=null;//接受者private Object data=null;//传递的数据private boolean flag=false;//指令的处理结果private String cmd=null;//服务端要做的指令private String result=null;//处理结果public String getSender() {return sender;}public void setSender(String sender) {this.sender = sender;}public String getReceiver() {return receiver;}public void setReceiver(String receiver) {this.receiver = receiver;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public String getCmd() {return cmd;}public void setCmd(String cmd) {this.cmd = cmd;}}

而 execute(CommandTranser msg)方法主要处理客户端向服务端发送的数据

由于我们只实现了两个功能  即登录 和聊天

所以execute方法主要代码如下

// 如果是登录请求if ("login".equals(msg.getCmd())) {UserService userService = new UserService();User user = (User) msg.getData();msg.setFlag(userService.checkUser(user));/** 如果登陆成功,将该客户端加入已经连接成功的map集合里面 并且开启此用户的接受线程*/if (msg.isFlag()) {// 将该线程加入连接成功的map集合SocketThread socketThread = new SocketThread();socketThread.setName(msg.getSender());socketThread.setSocket(socket);SocketList.addSocket(socketThread);msg.setResult("登陆成功");} else {msg.setResult("登录失败");}}// 如果是发送消息的指令 判断当前用户是否在线if ("message".equals(msg.getCmd())) {// 如果要发送的用户在线 发送信息if (SocketList.getSocket(msg.getReceiver()) != null) {msg.setFlag(true);} else {msg.setFlag(false);msg.setResult("当前用户不在线");}}return msg;}

当用户为login请求时,通过userservice查询数据库中是否有此用户,并返回结果

package cn.edu.xynu.service;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;import cn.edu.xynu.entity.User;
import cn.edu.xynu.util.DBHelper;/*** @author scx 客户的业务处理 只查询用户是否在数据库中存在*/
public class UserService {public boolean checkUser(User user) {PreparedStatement stmt = null;Connection conn = null;ResultSet rs = null;conn = DBHelper.getConnection();String sql = "select * from user where username=? and password =?";try {stmt = conn.prepareStatement(sql);stmt.setString(1, user.getUsername());stmt.setString(2, user.getPassword());rs = stmt.executeQuery();if (rs.next()) {return true;}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {if (rs != null)rs.close();if (stmt != null)stmt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return false;}
}

User类用户的实体类,只包括帐号 密码信息

package cn.edu.xynu.entity;import java.io.Serializable;/*** @author scx*    用户信息的实体类*/
public class User implements Serializable{private static final long serialVersionUID = 1L;private String username;private String password;public User() {super();}public User(String username, String password) {super();this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

而DBhelpher为连接数据库工具类

package cn.edu.xynu.util;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;/*** @author scx* 数据库*/
public class DBHelper {private static final String driver="com.mysql.jdbc.Driver";private static final String url="jdbc:mysql://localhost:3306/myqquser?useUnicode=true&charcterEncoding=UTF-8";private static final String username="root";private static final String password="";private static  Connection con=null;//静态块代码负责加载驱动static{try {Class.forName(driver);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static Connection getConnection(){if(con==null){try {con=DriverManager.getConnection(url, username, password);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return con;}
}

下一篇  
JAVA进阶案例 TCP编程之网络聊天工具(客户端)

全部源码点击下载

JAVA进阶案例 TCP编程之网络聊天工具(服务端)相关推荐

  1. JAVA进阶案例 TCP编程之网络聊天工具(客户端)

    首先附上登录操作 登录界面就不说了,直说业务处理.当点击登录之后 /** 如果点击了登录按钮 首先判断帐号或者密码是否为空 然后封装为CommandTranser对象 向服务器发送数据 服务器通过与数 ...

  2. socket编程(在线自动聊天工具) --Python3

    目录 @ 1.服务端只支持一个客户端连接 服务端程序(server.py): import socket# 创建服务端socket对象 server = socket.socket() # 绑定IP( ...

  3. 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具。QQ_Chat

    代码下载地址 原博客地址 QQ_Chat 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具. (内含报告) 工具: Eclipse.Navicat for MySQL ...

  4. 视频教程-网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天-Java

    网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天 IT行业资深从业者,7年资深Java高级开发,Java架构师.曾就职银行.电信等行业多家上市公司.担任项目负责人,软件架构师.有丰富 ...

  5. java进阶案例下载_java进阶案例

    java进阶案例: 数据类型,字符,数值,范围,布尔 :byte -128~127. 面向对象:protect :重载与构造 (一). this封装:static:继承:多态: 1.方法覆盖:supe ...

  6. 基于TCP协议的网络聊天室

    创建服务端程序 public class Server {public static void main(String[] args) {new Thread(new ServerTask()).st ...

  7. 【Socket网络编程】4.tcp和udp的客户端和服务端收发流程

    tcp和udp的客户端和服务端收发流程 1.udp服务器流程: 1.创建serverSocket 2.设置服务器地址 serverAddr 3.将serverSocket和serverAddr绑定 b ...

  8. 聊天系统设计与实现服务器代码,网络聊天工具系统的设计与实现.doc

    PAGE 综合课程设计报告 网络聊天工具系统的设计与实现 学生姓名: 指导教师: 所 在 系: 电 子 信 息 系 所学专业: 计算机科学与技术 年 级: PAGE 1 1 目 录 TOC \o &q ...

  9. 基于UDP协议的局域网网络聊天工具

    /* * 本程序实现了基于UDP协议的局域网网络聊天工具. * 参考网上的源码,发现一个calss就可以搞定. * ChatFrame类创建窗口,包含JTextField和TextArea. * 前者 ...

最新文章

  1. 微信小程序城市定位(百度地图API)
  2. 表表达式,Substring, CharIndex, 多行数据变同一行的用法
  3. python爬虫系列(1.3-关于cookie的认识)
  4. 第九次作业——测试报告与用户手册
  5. bootstrap-fileinput 应用
  6. linux last 命令年份,【帝联运维课堂】(第七十二期)Linux下last命令如何显示年份...
  7. Java通过Pattern类使用正则表达式
  8. Django-你想知道的都在这里
  9. python模块讲解_python模块详解
  10. flink java 并行度_flink solt和并行度
  11. CMS软件系统架构设计思考
  12. OpenCV-图像处理(03、Mat对象)
  13. visual foxpro
  14. 河海大学2021年硕士研究生招考公告
  15. java计算机毕业设计晨光文具店进销存系统设计与开发源码+数据库+系统+lw文档+部署
  16. 2018年Android面试题含答案
  17. 百度地图显示车辆运行轨迹(动态轨迹回放功能)
  18. PPT文字过少时,如何排版比较好
  19. kodi android 目录,如何在xbmc / kodi插件中创建多个目录?
  20. CAN2.0A 和CAN2.0B

热门文章

  1. 制度化规范化标准化精细化_打造精细化案件管理平台 制度化管理促执法规范化...
  2. 如何删除已安装的Windows服务
  3. 自己动手写数据库:并发管理的基本原理
  4. [移动端]移动端设备属性
  5. Vue-json-viewer 展示JSON格式数据
  6. 计算机课堂热身游戏,上电脑课时偷偷玩的3个游戏,这些都没玩过,别说自己玩过游戏!...
  7. 基于以太坊智能合约开发
  8. 支付宝RAS密钥生成器SHAwithRSA1024_V1.0.bat在win10运行闪退
  9. 计算机绘图与三维造型课后题,计算机绘图(中级):AutoCAD三维建模与深入运用上机实验指导...
  10. 多目标应用:MOGWO求解杆桁架问题(4-bar truss problem)