网络通信(QQ)

news/2024/11/29 10:56:29/

服务器

用户

package qq.QQServer.qqcommon;import java.io.Serializable;/*
表示一个用户信息*/
public class User implements Serializable {private static final long serialVersionUID = 1L;private String userId;//用户Idprivate String passwd;//用户密码public User(String userId, String passwd) {this.userId = userId;this.passwd = passwd;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getPasswd() {return passwd;}public void setPasswd(String passwd) {this.passwd = passwd;}
}

消息对象

package qq.QQServer.qqcommon;import java.io.Serializable;/*
客户端和服务器的消息对象*/
public class Message implements Serializable {private static final long serialVersionUID = 1L;private String sender;//发送者private String getter;//接收者private String content;//消息内容private String sendTime;//发送消息private String mesType;//消息类型 可以在接口定义消息类型//进行扩展 和文件相关成员private byte[] fileBytes;private int filelen = 0;private String dest;//将文件传输到。。private String src;//源文件路径public byte[] getFileBytes() {return fileBytes;}public void setFileBytes(byte[] fileBytes) {this.fileBytes = fileBytes;}public int getFilelen() {return filelen;}public void setFilelen(int filelen) {this.filelen = filelen;}public String getDest() {return dest;}public void setDest(String dest) {this.dest = dest;}public String getSrc() {return src;}public void setSrc(String src) {this.src = src;}public static long getSerialVersionUID() {return serialVersionUID;}public String getSender() {return sender;}public void setSender(String sender) {this.sender = sender;}public String getGetter() {return getter;}public void setGetter(String getter) {this.getter = getter;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getSendTime() {return sendTime;}public void setSendTime(String sendTime) {this.sendTime = sendTime;}public String getMesType() {return mesType;}public void setMesType(String mesType) {this.mesType = mesType;}
}

接口常量

package qq.QQServer.qqcommon;public interface MessageType {//在接口中定义一些常量String MESSAGE_LOGIN_SUCCEED = "1";//登录成功String MESSAGE_LOGIN_FAIT = "2";//登录失败String MESSAGE_COMM_MES = "3";//普通信息包String MESSAGE_GET_ONLINE_FRIEND = "4";//要求返回在线用户列表String MESSAGE_RET_ONLINE_FRIEND = "5";//返回在线用户列表String MESSAGE_CLIENT_EXIT = "6";//客户端请求退出String MESSAGE_To_All_MES = "7";//群发消息String MESSAGE_FILT_MES = "8";//文件消息
}
package qq.QQServer.qqserver.server;import qq.QQClient.qqcommon.Message;
import qq.QQClient.qqcommon.MessageType;
import qq.QQClient.qqcommon.User;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;/*
这是服务端*/
public class QQServer {private ServerSocket ss = null;//创建一个集合,存放多个用户,如果是这些用户,就是合法的//这里也可以使用ConcurrentHashMap,可以处理并发的集合,没有线程安全//HashMap没有处理线程安全,因此多线程不安全//ConcurrentHashMap 处理线程安全,即线程同步处理,在多线程下是安全的private static ConcurrentHashMap<String, User> validUsers = new ConcurrentHashMap<>();static {validUsers.put("100",new User("100", "123456"));validUsers.put("200",new User("200", "123456"));validUsers.put("300",new User("300", "123456"));validUsers.put("至尊宝",new User("至尊宝", "123456"));validUsers.put("紫霞仙子",new User("紫霞仙子", "123456"));validUsers.put("菩提老祖",new User("菩提老祖", "123456"));}//验证用户是否有效的方法private boolean checkUser(String userId, String passad){User user = validUsers.get(userId);if(user == null){//说明UserId不存在validUser 的key中return false;}if (!user.getPasswd().equals(passad)){//userId正确,但密码错误return false;}return true;}public QQServer(){//端口写在配置文件try {System.out.println("服务端在端口9999监听。。。。");ss = new ServerSocket(9999);while (true) { //当和某个客户端连接后继续监听,因此whileSocket socket = ss.accept();//启动推送新闻线程new Thread(new SendNewsToAllService()).start();//得到socket关联的对象输入流ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());User u = (User) ois.readObject();//读取客户端发送的User对象//创建一个Message对象,准备回复客户端Message message = new Message();//验证if (checkUser(u.getUserId(),u.getPasswd())){//登录通过message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);//将message对象回复给客户端oos.writeObject(message);//创建一个线程,和客户端保持通信,该线程需要有socket对象ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());//启动线程serverConnectClientThread.start();//吧该线程对象放入到一个集合中进行管理ManageClientThreads.addClientThread(u.getUserId(), serverConnectClientThread);} else {//登录失败System.out.println("用户 id" + u.getUserId() + " pwd " + u.getPasswd() + "验证失败");message.setMesType(MessageType.MESSAGE_LOGIN_FAIT);oos.writeObject(message);//关闭socketsocket.close();}}} catch (Exception e) {e.printStackTrace();} finally {//如果服务器退出while,说明服务端不在监听,因此关闭ServerSockettry {ss.close();} catch (IOException e) {e.printStackTrace();}}}
}

服务端线程

package qq.QQServer.qqserver.server;import qq.QQClient.qqcommon.Message;
import qq.QQClient.qqcommon.MessageType;import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;/*
该类的一个对象和某个客户端保持通信*/
public class ServerConnectClientThread extends Thread{private Socket socket;private String userId;public ServerConnectClientThread(Socket socket, String userId){this.socket = socket;this.userId = userId;}public Socket getSocket(){return socket;}@Overridepublic void run() {while (true){try {System.out.println("服务端和客户端" + userId + "保持通信,读取数据。。。");ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Message message = (Message) ois.readObject();//根据message的类型做相应的业务处理if (message.getMesType().equals(MessageType.MESSAGE_GET_ONLINE_FRIEND)){System.out.println(message.getSender() + "要在线用户列表");String onlineUser = ManageClientThreads.getOnlineUser();//返回message//构建一个message对象,返回给客户端Message message2 = new Message();message2.setMesType(MessageType.MESSAGE_RET_ONLINE_FRIEND);message2.setContent(onlineUser);message2.setGetter(message.getSender());//返回给客户端ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(message2);} else if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){//根据message获取getter id,然后在得到对应线程ServerConnectClientThread serverConnectClientThread =ManageClientThreads.getServerConnectClientThread(message.getGetter());//得到对应socket的对象输出流,将message对象转发给指定的客户端ObjectOutputStream oos =new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());oos.writeObject(message);//转发,提示,如果客户不在线,可以保存到数据库,就可以实现离线留言} else if (message.getMesType().equals(MessageType.MESSAGE_To_All_MES)){//需要遍历 管理线程的集合,把所以的线程的socket得到,然后把message进行转发HashMap<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();Iterator<String> iterator = hm.keySet().iterator();while (iterator.hasNext()){//取出在线用户IdString onLineUserId = iterator.next();if(!onLineUserId.equals(message.getSender())){//排除群发消息的这个用户//进行转发messageObjectOutputStream oos = new ObjectOutputStream(hm.get(onLineUserId).getSocket().getOutputStream());oos.writeObject(message);}}} else if (message.getMesType().equals(MessageType.MESSAGE_FILT_MES)){//根据gettterId 获取对于的线程 将message对象转发ObjectOutputStream oos =new ObjectOutputStream(ManageClientThreads.getServerConnectClientThread(message.getGetter()).getSocket().getOutputStream());oos.writeObject(message);}else if (message.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)){//客户端退出System.out.println(message.getSender() + "退出");ManageClientThreads.removeServerConnectClientThread(message.getSender());socket.close();//关闭连接//退出线程break;} else {System.out.println("其他类型的message暂时不处理");}} catch (Exception e) {e.printStackTrace();}}}
}

服务端线程管理

package qq.QQServer.qqserver.server;import java.util.HashMap;
import java.util.Iterator;public class ManageClientThreads {private static HashMap<String, ServerConnectClientThread> hm = new HashMap<>();public static HashMap<String, ServerConnectClientThread> getHm() {return hm;}//添加线程对象到hm集合public static void addClientThread(String userId, ServerConnectClientThread serverConnectClientThread){hm.put(userId, serverConnectClientThread);}//根据userId 返回ServerConnectClientThread线程public static ServerConnectClientThread getServerConnectClientThread(String userId){return hm.get(userId);}//增加一个方法,从集合中,移除某个线程对象public static void removeServerConnectClientThread(String userId){hm.get(userId);}//编写方法,返回在线用户列表public static String getOnlineUser(){//集合遍历,遍历hashmap的keyIterator<String> iterator = hm.keySet().iterator();String onlineUserList = "";while (iterator.hasNext()){onlineUserList += iterator.next().toString() + " ";}return onlineUserList;}
}

整体发送

package qq.QQServer.qqserver.server;import qq.QQClient.qqclient.utils.Utility;
import qq.QQClient.qqcommon.Message;
import qq.QQServer.qqcommon.MessageType;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;public class SendNewsToAllService implements Runnable{private Scanner scanner = new Scanner(System.in);@Overridepublic void run() {//为了多次使用while (true) {System.out.println("请输入服务器要推送的消息[输入exit退出推送服务]");String news = Utility.readString(100);if("exit".equals(news)){break;}//构建一个消息类型Message message = new Message();message.setSender("服务器");message.setMesType(MessageType.MESSAGE_To_All_MES);message.setContent(news);message.setSendTime(new Date().toString());;System.out.println("服务器推送消息给所有人说:" + news);//遍历当前所有的通信线程,得到socket,并发送messageHashMap<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();Iterator<String> iterator = hm.keySet().iterator();while (iterator.hasNext()) {String onLineUserId = iterator.next().toString();try {ObjectOutputStream oos = new ObjectOutputStream(hm.get(onLineUserId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}}}
}

启动服务器

package qq.QQServer.qqframe;import qq.QQServer.qqserver.server.QQServer;public class QQFrame {public static void main(String[] args) {new QQServer();}
}

客户端主体

package qq.QQClient.qqclient.view;import qq.QQClient.qqclient.messageclientservice.MessageClientService;
import qq.QQClient.qqclient.service.FileClientSerivice;
import qq.QQClient.qqclient.service.UserClientService;
import qq.QQClient.qqclient.utils.Utility;/*
客户端菜单界面*/
public class QQView {private boolean loop = true;//控制是否显示主菜单private String key = "";//接收用户键盘输入private UserClientService userClientService = new UserClientService();//对象用来登录服务器/注册用户private MessageClientService messageClientService = new MessageClientService();//对象用户的私聊//群发private FileClientSerivice fileClientSerivice = new FileClientSerivice();//该对象用于传输public static void main(String[] args){new QQView().mainMenu();System.out.println("客户端退出系统");}//显示主菜单private void mainMenu(){while (loop){System.out.println("============欢迎登录网络系统==========");System.out.println("\t\t 1 登录系统");System.out.println("\t\t 9 退出系统");System.out.print("请输入你的选择");key = Utility.readString(1);//根据用户输入,来出来不同逻辑switch (key){case "1":System.out.print("请输入用户号:");String userId = Utility.readString(50);System.out.print("请输入用密  码:");String pwd = Utility.readString(50);if(userClientService.checkUser(userId,pwd)){System.out.println("============欢迎(用户 " + userId + "登录成功==========");//进入二级菜单while (loop){System.out.println("\n============网络通信系统二级菜单(用户 " + userId + "==========");System.out.println("\t\t 1 显示在线用户列表");System.out.println("\t\t 2 群发消息");System.out.println("\t\t 3 私聊消息");System.out.println("\t\t 4 发送文件");System.out.println("\t\t 9 退出系统");System.out.print("请输入你的选择");key = Utility.readString(1);switch (key){case "1":userClientService.onlineFriendList();break;case "2":System.out.println("请输入想对大家说的话");String s = Utility.readString(100);messageClientService.sendMessageToAll(s, userId);break;case "3":System.out.print("请输入向聊天的用户号(在线):");String getterId = Utility.readString(50);System.out.println("请输入想说的话:");String content = Utility.readString(100);//编写一个方法,将消息发送给服务器端messageClientService.sendMessageToOne(content, userId, getterId);break;case "4":System.out.print("请输入你想把文件发送给的用户(在线用户):");getterId = Utility.readString(50);System.out.print("请输入发送文件的路径(形式 d:\\xx.jpg)");String src = Utility.readString(100);System.out.print("请输入把文件发送到对应的目录(形式 d:\\yy.jpg)");String dest = Utility.readString(100);fileClientSerivice.sendFileToOne(src,dest,userId,getterId);break;case "9"://调用一个方法,给服务器发送一个退出系统的messageuserClientService.logout();loop = false;break;}}} else {//登录服务器失败System.out.println("============登录失败===============");}break;case "2":loop = false;break;}}}}

用户登录等

package qq.QQClient.qqclient.service;import qq.QQClient.qqcommon.Message;
import qq.QQClient.qqcommon.MessageType;
import qq.QQClient.qqcommon.User;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;/*
该类完成用户登录验证和用户注册等功能*/
public class UserClientService {private User u = new User();private Socket socket;//根据suerId 和 pwd 到服务器验证用户是否合法public boolean checkUser(String userId, String pwd){boolean b = false;//创建User对象u.setUserId(userId);u.setPasswd(pwd);//链接服务器,发送u对象try {socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);//得到ObjOutpStrea对象ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(u);//发送User对象//读取从服务器回复的Message对象ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Message ms = (Message) ois.readObject();if(ms.getMesType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)){//登录OK//创建一个和服务器端保持通信的线程-》创建一个类ClientConnectServerThreadClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);//启动客户端线程clientConnectServerThread.start();//为了后面客户端的扩展,我们将线程放入到集合管理MessageClientConnectServerThread.addClientConnectServerThread(userId, clientConnectServerThread);b = true;} else {//如果登录失败 我们就不能启动服务器通信的线程,关闭socketsocket.close();}} catch (Exception e) {e.printStackTrace();}return b;}//向服务器请求在线用户列表public void onlineFriendList(){//发送一个Message,类型MESSAGE_GET_ONLINE_FRIENDMessage message = new Message();message.setMesType(MessageType.MESSAGE_GET_ONLINE_FRIEND);message.setSender(u.getUserId());//发送给服务器try {//从管理线程的集合中,通过userID,得到这个线程ClientConnectServerThread clientConnectServerThread =MessageClientConnectServerThread.getClientConnectServerThread(u.getUserId());//通过这个线程得到关联的socketSocket socket = clientConnectServerThread.getSocket();//得到当前线程的Socket 对于的ObjectOutputStream对象ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(message);//发送一个Message对象,向服务端要求在线用户列表} catch (IOException e) {e.printStackTrace();}}//编写方法,退出客户端,并给服务端发送一个退出系统的message对象public void logout(){Message message = new Message();message.setMesType(MessageType.MESSAGE_CLIENT_EXIT);message.setSender(u.getUserId());try {//ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());ObjectOutputStream oos =new ObjectOutputStream(MessageClientConnectServerThread.getClientConnectServerThread(u.getUserId()).getSocket().getOutputStream());oos.writeObject(message);System.out.println(u.getUserId() + "退出系统");System.exit(0);//退出进程} catch (IOException e) {e.printStackTrace();}}
}

线程问题

package qq.QQClient.qqclient.service;import qq.QQClient.qqcommon.Message;
import qq.QQClient.qqcommon.MessageType;import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;public class ClientConnectServerThread extends Thread{//该线程要Socketprivate Socket socket;public ClientConnectServerThread(Socket socket){this.socket = socket;}@Overridepublic void run() {//因为Thread需要在后台和服务器通信,因此我们while循环while (true){try {System.out.println("客户端线程,等待从服务器端读取发送的消息");ObjectInputStream osi = new ObjectInputStream(socket.getInputStream());//如果服务器没有发送Message对象,线程会阻塞在这Message message = (Message) osi.readObject();//判断Message类型,然后做相应的处理if(message.getMesType().equals(MessageType.MESSAGE_RET_ONLINE_FRIEND)){//取出在线列表信息,并显示String[] onlineUsers = message.getContent().split(" ");System.out.println("\n===============当前在线用户列表================");for (int i = 0; i < onlineUsers.length; i++) {System.out.println("用户: " + onlineUsers[i]);}} else if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){//吧从服务器转发的消息,显示到控制台就行System.out.println("\n" + message.getSender()+ "对 " + message.getGetter() + " 说 " + message.getContent());} else if (message.getMesType().equals(MessageType.MESSAGE_To_All_MES)){//显示在客户端的控制台System.out.println("\n" + message.getSender() + " 对大家说 " + message.getContent());} else if (message.getMesType().equals(MessageType.MESSAGE_FILT_MES)){//如果是文件消息System.out.println("\n" + message.getSender() + " 给 "+ message.getGetter()+ " 发送文件:" + message.getSrc() + " 到我的电脑目录 " + message.getDest());//取出message的文件字节数组,通过文件输出流写道磁盘FileOutputStream fileOutputStream = new FileOutputStream(message.getDest());fileOutputStream.write(message.getFileBytes());fileOutputStream.close();System.out.println("\n保存文件成功");} else {System.out.println("是其他类型的message,暂时不处理");}} catch (Exception e) {e.printStackTrace();}}}public Socket getSocket() {return socket;}
}

线程管理

package qq.QQClient.qqclient.service;import java.util.HashMap;/*
该类管理客户端连接到服务端的线程*/
public class MessageClientConnectServerThread {//我们吧多个线程放入一个HashMap集合,key就是用户id,value就是线程private static HashMap<String, ClientConnectServerThread> hm = new HashMap<>();//将某个线程加入到集合public static void addClientConnectServerThread(String userId, ClientConnectServerThread clientConnectServerThread){hm.put(userId,clientConnectServerThread);}//通过userId 得到对应的线程public static ClientConnectServerThread getClientConnectServerThread(String userId){return hm.get(userId);}
}

文件管理

package qq.QQClient.qqclient.service;import qq.QQClient.qqcommon.Message;
import qq.QQClient.qqcommon.MessageType;import java.io.*;public class FileClientSerivice {public void sendFileToOne(String src, String dest, String senderId, String getterId){//读取src文件 ——》 messageMessage message = new Message();message.setMesType(MessageType.MESSAGE_FILT_MES);message.setSender(senderId);message.setGetter(getterId);message.setSrc(src);message.setDest(dest);//需要将文件读取FileInputStream fileInputStream = null;byte[] fileBytes = new byte[(int) new File(src).length()];try {fileInputStream = new FileInputStream(src);fileInputStream.read(fileBytes);//将src文件读入到程序的字节数组//将文件对应的字节数组设置messagemessage.setFileBytes(fileBytes);} catch (Exception e) {e.printStackTrace();}finally {if (fileInputStream != null){try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("\n" + senderId + " 给 " + getterId + " 发送文件: " + src + "到对方的电脑目录 " + dest);try {ObjectOutputStream oos =new ObjectOutputStream(MessageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}
}
package qq.QQClient.qqclient.messageclientservice;import qq.QQClient.qqclient.service.MessageClientConnectServerThread;
import qq.QQClient.qqcommon.Message;
import qq.QQServer.qqcommon.MessageType;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;public class MessageClientService {public void sendMessageToAll(String content, String senderId){//构建messageMessage message = new Message();message.setMesType(MessageType.MESSAGE_To_All_MES);//群发消息message.setSender(senderId);message.setContent(content);message.setSendTime(new Date().toString());//发送数据到message对象System.out.println(senderId + " 对大家说 " + content);//发送给服务端try {ObjectOutputStream oos =new ObjectOutputStream(MessageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}public void sendMessageToOne(String content, String senderId, String getterId){//构建messageMessage message = new Message();message.setMesType(MessageType.MESSAGE_COMM_MES);//普通的聊天消息message.setSender(senderId);message.setGetter(getterId);message.setContent(content);message.setSendTime(new Date().toString());//发送数据到message对象System.out.println(senderId + "对" + getterId + "说" + content);//发送给服务端try {ObjectOutputStream oos =new ObjectOutputStream(MessageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());oos.writeObject(message);} catch (IOException e) {e.printStackTrace();}}
}


http://www.ppmy.cn/news/246548.html

相关文章

Q:

在a文件中改变C文件的IP&#xff0c;b文件的url也会发生变化 背景&#xff1a; 之前url是固定的&#xff0c;只需要向一台服务器发送请求&#xff0c;现在需要向不同的服务器发送请求。在a文件确定到底往那个服务器发送请求a.py def test_API(self):IP "11" # 改变…

猛Q

http://blog.csdn.net/Raptor

QNetwork

Tcp/IP TCP/IP是一套用于网络通信的协议集合或者系统 TCP/IP体系&#xff1a; TCP报文格式&#xff1a; 三次握手连接TCP 四次挥手断开TCP QHostAddress 枚举类型含义QHostAddress::Null空地址对象&#xff0c;相当于QHostAddress()QHostAddress::BroadcastIPv4广播地…

腾讯Tencent

1、一个商场进行一场抽奖活动&#xff0c;其中有两个奖项&#xff0c;第一个奖项A抽中的概率是1/6&#xff0c;第二个奖项B抽中的概率是5/6&#xff1b;用C语言编码实现这个抽奖程序。 题目通过一个XML文档给出。 生成一个真随机数。 随机数对6取余&#xff0c;得到的余数一定…

开源项目——小Q聊天机器人V1.4

声明&#xff1a;本博客内容只为学习交流使用&#xff0c;未经本人同意&#xff0c;禁止商用&#xff0c;此应用已有上线版本&#xff0c;严禁盗版&#xff01;&#xff01;&#xff01; 小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊…

QT笔记——Q_Q 和Q_D 学习

在源码中&#xff0c;我们会经常看到Q_Q 和 Q_D 这两个东西 &#xff0c;很好奇&#xff0c;就去网上搜索了一些和 查看了一些源码 部分 一&#xff1a;Q_D相关宏 #define Q_D(Class) Class##Private * const d d_func()Q_D(Test); //展开后 是一个 私有类的指针常量 Test…

基于QT平台webapi科大讯飞语音机器人2.0

本博是针对上一个版本的语音机器人更新&#xff0c;主要更新内容为对iat的支持&#xff0c;即使用语音交互取代文字输入的方式&#xff0c;由于之前忙于其他事情一直没来的及更新&#xff0c;以后会将语音机器人一直做下去&#xff0c;添加更多的功能和大家分享。 那么先来看看…

qq等级计算机在线,I'M QQ - QQ官方网站

QQ等级说明 QQ等级规则 通过累积活跃天数&#xff0c;您可以获取相应的QQ等级。累积在线天数将有机会参加我们即将推出的奖励活动和享受相关的优惠服务&#xff0c;而不影响正常的QQ使用。 拥有QQ在线等级为太阳级别及以上的用户&#xff0c;可享受任意上传设置QQ自定义头像和建…