前言:昨天我们已经初步学习了网络编程到底是怎么一回事儿,今天在此基础上继续学习网络编程,利用网络编程实现 QQ上的发送消息,群聊,私聊等功能。

首先我们来回顾一下昨天的两点基础知识:

1、建立服务器端

服务器建立通信ServerSocket

服务器建立Socket接收客户端连接

建立IO输入流读取客户端发送的数据

建立IO输出流向客户端发送数据消息

2、建立客户端

创建Socket通信,设置通信服务器的IP和Port

建立IO输出流向服务器发送数据消息

建立IO输入流读取服务器发送来的数据消息

群聊思路分析:

首先我们都知道,群聊是什么形式的,群聊就是一个人发的消息,所有人都可见,但是这要在程序中怎样体现这种关系呢?

首先我们必须明确知道的是,客户端只能向服务器端发送内容,服务器端只能接受客户端发送来的数据,客户端的其他需求可以在发送的字符里面体现。因为QQ的聊天中,分私聊和群聊,所以服务器端就要区分什么内容是群聊什么是私聊,谁私聊谁,为了解决这些问题,我们必须给客户端和服务器端一个统一的规范,这个统一的规范是让服务器端知道发送的是群聊消息还是私聊消息,谁私聊谁的问题。

下面我们定义的规范如下:

例如:p+ wll♥ 晚上好 p+——>服务器译为:私聊wll发送的内容是晚上好

a+ 大家好 a+——> 译为:是群发消息,发送的内容是:大家好

下面我们new一个interface,存放这些规范,如下所示:

//定义一套规范

public interface Chatinterface {

//登录

String LOGIN_FLAG = "u+";

//私聊

String PRIVATE_FLAG="P+";

//群聊

String PUBLIC_FLAG = "a+";

// 分隔符

String SPLTI_FLAG = "♥";

// 成功

String SUCCESS = "1";

//失败

String FAILE = "-1";

}

根据昨天学习的知识,我们知道要定义服务器端和客户端,但是谁来管理登录,私聊群聊呢?所以这里我们要定义一个类来管理。

以下我们定义一个UserManager类来管理,相关注释如下所示:

public class UseraManager {

//保存所有用户的信息

private Map users = new HashMap<>();

//判断银狐是否已经登录

public boolean isLogined(String name) {

//遍历数组

for (String key : users.keySet()) {

if (key.equals(name)) {

return true;

}

}

return false;

}

//保存当前登录的用户信息

public void save(String name, Socket socket) {

users.put(name, socket);

}

//通过用户名找到对应的socket

public Socket socketName(String name) {

return users.get(name);

}

//通过socket找到对应的名称

public String nameBySocket(Socket socket) {

for (String key : users.keySet()) {

//取出这个key对应的socket

if (socket == users.get(key)) {

return key;

}

}

return null;

}

//获取所有人的socket

public synchronized Collection allUsers (){

return users.values();

}

}

`2.建立客户端:

我们知道客户端首先要做的就是建议socket,然后向服务器端发送数据和接收服务器端的数据。第一步:new一个Client类,第二步:创建socket,第三步:创建发送和接收的数据流,格式如下:

//1.创建用于通信的socket

// 指明和谁通信:ip地址 端口号

Socket socket = new Socket("192.168.43.32",8989);

//2. 接收服务器端的数据

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//3.读取服务器端发来的数据

String line = null;

while ((line = br.readLine()) != null){

System.out.println(line);

}

3,多线程,不管是服务器端还是客户端都要接受数据和发送数据,但早发送数据的同时使可以接受数据的,早接收数据的同时,也是可以发送数据的,所以在客户端和服务器端都要使用多线程,服务器端的子线程用来处理客户端发送来的数据:判断是否已经登录,判断是群聊还是私聊,判断私聊给谁,

1.判断是否已经登录如下:

判断用户名是否已经登录

if(Server.manager.isLogined(name)){

//登录过了

ps.println(Chatinterface.FAILE);

} else {

//没有登录过

Server.manager.save(name,socket);

ps.println(Chatinterface.SUCCESS);

}

}

2.判断是不是私聊:

//判断是不是私聊

else if(line.startsWith(Chatinterface.PRIVATE_FLAG)&&line.endsWith(Chatinterface.PRIVATE_FLAG)){

//用户名和聊天内容

//获取信息

int len =line.length()-2;

String msg = line.substring(2,len);

//分割

String[] itens = msg.split(Chatinterface.SPLTI_FLAG) ;

String name = itens[0];

String massage = itens[1];

//通过用户名找到对应的socket

Socket destsocket = Server.manager.socketName(name);

PrintStream desPS = new PrintStream(destsocket.getOutputStream());

//获取当前用户的名称

String currentName = Server.manager.nameBySocket(socket);

//发的送私聊信息

desPS.println(currentName +"想你发来私聊"+massage);

}

因为经过第一步,说明已经登录,经过第二步:说明不是群聊,所以就只用私聊了,处理私聊的大妈如下:

int len =line.length()-2;

String msg = line.substring(2,len);

String currentNmae = Server.manager.nameBySocket(socket);

//遍历所有的用户信息

Collection sockets = Server.manager.allUsers();

for(Socket s :sockets){

PrintStream temps = new PrintStream(s.getOutputStream());

temps.println(currentNmae+"发来群聊"+msg);

}

整个代码如下:

客服端:

public class Client {

public static void main(String[] args ){

//BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

BufferedReader br = null;

PrintStream ps = null;

BufferedReader bufferedReader = null;

try ( Socket socket = new Socket("192.168.43.32",8898);){

br = new BufferedReader(new InputStreamReader(System.in));

ps= new PrintStream(socket.getOutputStream());

bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

while (true){

//接受终端输入信息

String line = JOptionPane .showInputDialog("请登录");

// String line = br.readLine();

//拼接登录格式

String loginStr = Chatinterface.LOGIN_FLAG+line+Chatinterface.LOGIN_FLAG;

//发送给服务器

ps.println(loginStr);

//接受服务器端返回的结果

String result = bufferedReader.readLine();

if(result.equals(Chatinterface.SUCCESS)){

System.out.println("登录成功");

break;

}else {

System.out.println("用户已存在,请重新登录");

}

}

//登录成功

//发送数据,接受数据

//开启线程处理服务器端的输入

new ClientThread(socket).start();

String line ;

while ((line = br.readLine())!=null){

ps.println(line);

}

} catch (IOException e) {

}

}

}

子线程:

class ClientThread extends Thread{

private Socket socket ;

public ClientThread(Socket socket ){

this.socket = socket;

}

@Override

public void run() {

BufferedReader br = null;

try{

br= new BufferedReader(new InputStreamReader(socket.getInputStream()));

String line = null;

while ((line = br.readLine())!=null){

System.out.println(line);

}

} catch (IOException e) {

System.out.println("网络出错");

}finally {

try {

if (br != null) {

br.close();

}

if(socket != null){

socket.close();

}

}catch (IOException e) {

}

}

}

}

服务器端:

public class Server {

//用于保存每个与用户姓名和socket

public static UseraManager manager = new UseraManager();

public static void main(String[] args){

try( ServerSocket ss = new ServerSocket(8898);) {

while (true) {

Socket socket = ss.accept();

//让子线程处理这个Socket

new ServerThread(socket).start();

}

} catch (IOException e) {

}

}

}

服务器端子线程:

class ServerThread extends Thread{

private Socket socket;

public ServerThread (Socket socket){

this.socket = socket;

}

@Override

public void run() {

BufferedReader br= null;

PrintStream ps = null;

//登录

//1.获取输入流

try {

br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

ps= new PrintStream(socket.getOutputStream() );

String line =null;

while ((line = br.readLine()) !=null){

if(line.startsWith(Chatinterface.LOGIN_FLAG)&&(line.endsWith(Chatinterface.LOGIN_FLAG))){

// String [] items= line.substring(2).split("u+");

// String name =items[0];

String name = line.substring(2,line.length()-3);

//判断用户名是否已经登录

if(Server.manager.isLogined(name)){

//登录过了

ps.println(Chatinterface.FAILE);

} else {

//没有登录过

Server.manager.save(name,socket);

ps.println(Chatinterface.SUCCESS);

}

}

//判断是不是私聊

else if(line.startsWith(Chatinterface.PRIVATE_FLAG)&&line.endsWith(Chatinterface.PRIVATE_FLAG)){

//用户名和聊天内容

//获取信息

int len =line.length()-2;

String msg = line.substring(2,len);

//分割

String[] itens = msg.split(Chatinterface.SPLTI_FLAG) ;

String name = itens[0];

String massage = itens[1];

//通过用户名找到对应的socket

Socket destsocket = Server.manager.socketName(name);

PrintStream desPS = new PrintStream(destsocket.getOutputStream());

//获取当前用户的名称

String currentName = Server.manager.nameBySocket(socket);

//发的送私聊信息

desPS.println(currentName +"想你发来私聊"+massage);

}else{

int len =line.length()-2;

String msg = line.substring(2,len);

String currentNmae = Server.manager.nameBySocket(socket);

//遍历所有的用户信息

Collection sockets = Server.manager.allUsers();

for(Socket s :sockets){

PrintStream temps = new PrintStream(s.getOutputStream());

temps.println(currentNmae+"发来群聊"+msg);

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

运行结果:

总结:只是点开始综合了,但是逻辑还是简单的,前面的基础只是有点遗忘的,现在的去看看前面的,有种感觉就是,学习一个只是点的时候不知道他的具体作用,到真正的实战中才能知道对这个只是点到底了解多少,还需要继续努力。

java 仿qq 传文件_java网络编程实现QQ发消息文件,图片等内容相关推荐

  1. java 开发文档协作_Java 网络编程---分布式文件协同编辑器设计与实现

    目录: 第一部分:Java网络编程知识 (一)简单的Http请求 一般浏览网页时,使用的时Ip地址,而IP(Internet Protocol,互联网协议)目前主要是IPv4和IPv6. IP地址是一 ...

  2. java seek指针 换行符_Java网络编程探究|乐字节

    大家好,我是乐字节小乐,上次给大家讲述了Java中的IO流之输出流|乐字节,本文将会给大家讲述网络编程. 主要内容如下: 网络 网络分层 IP位置 端口port 网络编程 一. 网络 1.概念 网络即 ...

  3. java上传网络图片_java网络编程之图片上传

    输入输出流核心代码 所有的文件传输都是靠流,其中文件复制最具代表性.输入流和输出流,从输入流中读取数据写入到输出流中. InputStream in =输入源; OutputStream os=输出目 ...

  4. Java网络编程基础_Java网络编程基础篇

    一.前言 网络通讯在系统交互中是必不可少的一部分,无论是面试还是工作中都是绕不过去的一部分,本节我们来谈谈Java网络编程中的一些知识,本chat内容如下: 网络通讯基础知识,剖析网络通讯的本质和需要 ...

  5. 2018-2019-2 20175227张雪莹《Java程序设计》实验五 《网络编程与安全》

    2018-2019-2 20175227张雪莹<Java程序设计> 实验五 <网络编程与安全> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:20 ...

  6. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载

    前言:iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载是在前篇iOS开发之网络编程--使用NSURLConnection实现大文件下载的基础上进行    断点续传的设置 ...

  7. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  8. (转)C#网络编程(订立协议和发送文件) - Part.4

    源码下载:http://www.tracefact.net/SourceCode/Network-Part4.rar C#网络编程(订立协议和发送文件) - Part.4 文件传输 前面两篇文章所使用 ...

  9. 20165230 《Java程序设计》实验五《网络编程与安全》实验报告

    20165230 <Java程序设计>实验五<网络编程与安全>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:田坤烨 学号:20165230 成绩: ...

最新文章

  1. 五年磨砺:微软Vista开发过程全记录
  2. 原生 Java 客户端进行消息通信
  3. 【opencv4】opencv视频教程 C++ 7、手动调整图像亮度与对比度 g(i, j) = αf(i, j) + β(点操作与邻域操作概念)
  4. C++ Opengl 绘制二次几何体源码
  5. @async注解_史上最全的java spring注解
  6. Linux 随机启动 Mysql​
  7. 【Python可视化】Windows 10系统上Pyecharts安装教程
  8. [JavaWeb-XML]约束(DTD,Schema)
  9. Linux服务器编程 用SIGURG检测带外数据是否到达
  10. 一次磁盘满的系统故障
  11. [转载] python numpy np.exp()函数
  12. PCM data flow - 3 - ASoC codec driver
  13. Struts,Spring 等开源项目svn 地址
  14. 【在线电子书制作】云展网教程 | 文本复制按钮
  15. 【论文阅读】基于深度神经网络的人体运动姿态估计与识别
  16. 笔记本电脑CPU低压、标压、高压的区别
  17. 双系统时间不一致问题
  18. STM32平台下的TM1812驱动
  19. 检测报告上CNAS、CMA资质含义及联系
  20. 管理-领导:领导百科

热门文章

  1. Google Chrome 背后的天才
  2. 电脑屏幕突然变成绿色的了
  3. json数据解析(json数据解析 前端)
  4. 一起来了解2018中国智能手机市场竞争态势与用户行为数据!
  5. spring中的Aware接口详解
  6. [案例]网易云音乐的个性化推荐
  7. python:关于三维装箱问题的算法研究-2
  8. Python实现循环移位操作
  9. 20000元!魅族史上最贵的手机:无开孔+无按键,为什么会怀才不遇
  10. 手把手教你做一个CSS 3D云