简单模拟qq聊天程序(TCP版)
来源:互联网 发布:java获取上下文路径 编辑:程序博客网 时间:2024/05/01 15:28
本程序特点:
1.分为client,server,tool 3个包,实现了多个任意客户端之间,进行通信
2.由于使用了包头+包体的信息传递格式,所以可以发送任意长度信息
3.由于没有界面,发送信息时需要指定目标id
一、client包:
public class Client { private static final String HOST = "127.0.0.1"; private static final int PORT = 9999; Socket socket ; Scanner in = new Scanner(System.in); public void init(){ try { //登陆 if(login()){ //开启读取服务器端线程 new Thread(new Receive(socket)).start(); //一直读取控制台 while (true){ if(in.hasNextLine()){ //检测消息是否合法 String temp = in.nextLine(); if(temp.contains(":")){ byte [] content = temp.getBytes(); Tool.write(socket, content); }else { System.out.println("信息格式不对, 目标id:消息内容"); } } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { try { socket.close(); }catch (Exception e){ e.printStackTrace(); } } } private boolean login() throws IOException { boolean b = false; System.out.println("请输入用户名密码:"); String username = in.next(); String password = in.next(); socket = new Socket(HOST,PORT); //登陆检测 Tool.write(socket,(username+" "+password).getBytes()); String flag = new String(Tool.read(socket)); if( flag.equals("true")){ b = true; } in.nextLine(); return b; }}客户端接受信息线程
public class Receive implements Runnable { Socket socket = null; public Receive(Socket socket){ this.socket = socket; } public void run() { try { while(true){ String data = new String(Tool.read(socket)); if(data.contains(":")){ System.out.println(data.split(":")[1]); }else { System.out.println(data); } } } catch (Exception e) { e.printStackTrace(); } }}
二、server包
public class Server { private ServerSocket serverSocket; public void init(){ try { serverSocket = new ServerSocket(9999); System.out.println("服务器端--开始监听"); while(true){ Socket socket = serverSocket.accept(); String username = null; //用户检测 if((username = checkUser(socket)) != null){ ClientHandel hm = new ClientHandel(socket,username); Thread t = new Thread(hm); t.start(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 返回用户id * @param socket * @return * @throws IOException */ private String checkUser(Socket socket) throws IOException { String b = null; byte [] content = Tool.read(socket); String data [] = new String(content).split(" "); String username = data[0]; String password = data[1]; b= username; //这里可以连接数据库进行校验 Tool.write(socket,"true".getBytes()); return b; }}
服务器端处理客户端线程
保存所有的socket对象,以用户的id为key
public class ClientHandel implements Runnable { private String username; private static HashMap<String, Socket> clientSocket = new HashMap<String, Socket>(); public static int count = 0; Socket socket = null; public ClientHandel(Socket socket, String username) { this.username = username; count++; this.socket = socket; clientSocket.put(username, socket); System.out.println("用户" + count + "接入"); } @Override public void run() { try { while (true) { //读取客户端内容 byte[] data = Tool.read(socket); //解析目标线程的key String key = getKey(data); System.out.println(new String(data)); if (data.length > 1 && key != null) { //传递给指定线程 Tool.write(clientSocket.get(key), data); } } } catch (Exception e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } private String getKey(byte[] data) throws IOException { String key = new String(data).split(":")[0]; if (!clientSocket.containsKey(key)) { Tool.write(socket, "该用户不在线".getBytes()); return null; } return key; }}
封装了读取,和写入方法,客户端和服务器端都会用到
public class Tool { public static byte[] read(Socket socket) throws IOException { BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); //包头 byte[] head = new byte[4]; bis.read(head); byte[] data = new byte[Tool.byteArrayToInt(head)]; //包体 bis.read(data); return data; } public static void write(Socket socket, byte[] content) throws IOException { //包头,固定4个字节,包含包体长度信息 byte [] head = Tool.intToByteArray1(content.length); BufferedOutputStream bis = new BufferedOutputStream(socket.getOutputStream()); bis.write(head); bis.flush(); //包体 bis.write(content); bis.flush(); } //int 转字节数组 public static byte[] intToByteArray1(int i) { byte[] result = new byte[4]; result[0] = (byte)((i >> 24) & 0xFF); result[1] = (byte)((i >> 16) & 0xFF); result[2] = (byte)((i >> 8) & 0xFF); result[3] = (byte)(i & 0xFF); return result; } public static byte[] intToByteArray2(int i) throws Exception { ByteArrayOutputStream buf = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(buf); out.writeInt(i); byte[] b = buf.toByteArray(); out.close(); buf.close(); return b; } //字节数组转int public static int byteArrayToInt(byte[] b) { int intValue=0; for(int i=0;i<b.length;i++){ intValue +=(b[i] & 0xFF)<<(8*(3-i)); } return intValue; }}
测试-客户端:
public class Main { public static void main(String args[]){ new Client().init(); }}
测试-服务器端:
public class Main { public static void main(String args[]){ new Server().init(); }}
结果:
1 0
- 简单模拟qq聊天程序(TCP版)
- Socket编程------模拟QQ聊天(TCP)
- 初学java之模拟QQ聊天软件(简单实现)
- 简单版QQ聊天
- Delphi简单TCP聊天程序
- Qt程序聊天弹屏问题简单解决方法(类似QQ聊天聊天窗口弹屏)
- JAVA学习第六十课 — UDP协议 &基于多线程模拟简单的QQ聊天程序
- 简单QQ网络聊天机程序
- Delphi简单TCP聊天程序(二):双向传输
- Delphi简单TCP聊天程序(三):登录注册功能
- Linux TCP实现简单聊天程序
- 一个超级简单的tcp聊天程序
- 利用TCP实现简单聊天程序
- 学习socket(一) TCP简单聊天程序
- 模拟QQ聊天窗口
- java用socket和serversocket实现一对一聊天(java实现简单的TCP聊天程序)
- linux 下简单的模拟QQ 聊天过程 UDP 通讯
- 模拟QQ聊天程序_服务器端_网络编程
- 分治算法的时间复杂度分析
- 第三周练习——二分法2 方程求解
- Remove Element
- 浅谈一下JAVA对象,对象引用以及对象赋值
- 网易 电面
- 简单模拟qq聊天程序(TCP版)
- mac mysql-python mysql_config not found
- 双重检查锁定在JAVA单例中应用的杯具!
- 通过putty连接VM中安装的ubuntu
- 超高速缓存的最佳实践
- 李刚 JavaSE 47集 局部变量
- PAT 1054. The Dominant Color
- 第一周算法概论作业
- HDU部分题目算法归纳(转自http://blog.csdn.net/lizuqingblog/article/details/17392941)