900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > JAVA进阶案例 TCP编程之网络聊天工具(服务端)

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

时间:2019-02-15 02:39:42

相关推荐

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

实现分析、

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 .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 .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编程之网络聊天工具(客户端)

全部源码点击下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。