http://blog.csdn.net/shimiso/article/details/8816540

关于Smack编程库,前面我们提到,它是面向Java端的api,主要在PC上使用,利用它我们可以向openfire服务器注册用户,发送消息,并且可以通过监听器获得此用户的应答消息,以及构建聊天室,分组,个人通讯录等等。

下面我们写几个程序小例子测试一下。

(1)登录操作

  1. PPConnection.DEBUG_ENABLED = true;
  2. AccountManager accountManager;
  3. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
  4. "192.168.1.78", Integer.parseInt("5222"), "csdn.shimiso.com");
  5. // 允许自动连接
  6. connectionConfig.setReconnectionAllowed(true);
  7. connectionConfig.setSendPresence(true);
  8. Connection connection = new XMPPConnection(connectionConfig);
  9. try {
  10. connection.connect();// 开启连接
  11. accountManager = connection.getAccountManager();// 获取账户管理类
  12. } catch (XMPPException e) {
  13. throw new IllegalStateException(e);
  14. }
  15. // 登录
  16. connection.login("admin", "admin","SmackTest");
  17. System.out.println(connection.getUser());
  18. connection.getChatManager().createChat("shimiso@csdn.shimiso.com",null).sendMessage("Hello word!");

运行结果:

在login中一共有三个参数,登录名,密码,资源名,可能有人不明白资源名到底是什么意思,其实就是客户端的来源,客户端的名称,如果不写它默认就叫smack,如果你用相同的账户不同的资源名和同一个人发三条消息,那将会弹出三个窗口,而不是一个窗口。
同时smack还为我们提供了非常好的调试工具Smack Debug,利用该工具我们可以准确的捕获详细的往返报文信息。

(2)下面我们继续写个聊天的例子:

  1. PPConnection.DEBUG_ENABLED = true;
  2. AccountManager accountManager;
  3. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
  4. "192.168.1.78", Integer.parseInt("5222"), "csdn.shimiso.com");
  5. // 允许自动连接
  6. connectionConfig.setReconnectionAllowed(true);
  7. connectionConfig.setSendPresence(true);
  8. Connection connection = new XMPPConnection(connectionConfig);
  9. try {
  10. connection.connect();// 开启连接
  11. accountManager = connection.getAccountManager();// 获取账户管理类
  12. } catch (XMPPException e) {
  13. throw new IllegalStateException(e);
  14. }
  15. // 登录
  16. connection.login("admin", "admin","SmackTest3");
  17. ChatManager chatmanager = connection.getChatManager();
  18. Chat newChat = chatmanager.createChat("shimiso@csdn.shimiso.com", new MessageListener() {
  19. public void processMessage(Chat chat, Message message) {
  20. if (message.getBody() != null) {
  21. System.out.println("Received from 【"
  22. + message.getFrom() + "】 message: "
  23. + message.getBody());
  24. }
  25. }
  26. });
  27. Scanner input = new Scanner(System.in);
  28. while (true) {
  29. String message = input.nextLine();
  30. newChat.sendMessage(message);
  31. }

运行结果:

这里我们用Scanner来捕捉用户在控制台的键盘操作,将信息发出,同时创建了一个MessageListener监听,在其中强制实现processMessage方法即可捕获发回的信息,在初次使用上还是较为容易上手的,我们只要细心查看API即可逐步深入下去。

(3)除了聊天以外我们经常还能想到就是广播

需要给所有在线的用户发送一个通知,或者给所有在线和离线的用户全发送,我们先演示如何给在线用户发送一个广播:

  1. PPConnection.DEBUG_ENABLED = false;
  2. AccountManager accountManager;
  3. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
  4. "192.168.1.78", Integer.parseInt("5222"), "csdn.shimiso.com");
  5. // 允许自动连接
  6. connectionConfig.setReconnectionAllowed(true);
  7. connectionConfig.setSendPresence(true);
  8. Connection connection = new XMPPConnection(connectionConfig);
  9. try {
  10. connection.connect();// 开启连接
  11. accountManager = connection.getAccountManager();// 获取账户管理类
  12. } catch (XMPPException e) {
  13. throw new IllegalStateException(e);
  14. }
  15. connection.login("admin", "admin","SmackTest3");
  16. Message newmsg = new Message();
  17. newmsg.setTo("shimiso@csdn.shimiso.com");
  18. newmsg.setSubject("重要通知");
  19. newmsg.setBody("今天下午2点60分有会!");
  20. newmsg.setType(Message.Type.headline);// normal支持离线
  21. connection.sendPacket(newmsg);
  22. connection.disconnect();

运行结果:

将参数设置为Message.Type.normal即可支持离线广播,openfire系统会自动判断该用户是否在线,如果在线就直接发送出去,如果不在线则将信息存入ofoffline表,现在我将shimiso用户退出登录,再给它发消息,我们可以进入openfire库的ofoffline表中,非常清楚看到里面躺着一条离线消息记录是发给shimiso这个用户的

(4)那么我们如何让shimiso这个用户一登陆就取到离线消息呢?

请看如下代码

  1. PPConnection.DEBUG_ENABLED = false;
  2. AccountManager accountManager;
  3. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
  4. "192.168.1.78", Integer.parseInt("5222"), "csdn.shimiso.com");
  5. // 允许自动连接
  6. connectionConfig.setReconnectionAllowed(true);
  7. connectionConfig.setSendPresence(false);//不要告诉服务器自己的状态
  8. Connection connection = new XMPPConnection(connectionConfig);
  9. try {
  10. connection.connect();// 开启连接
  11. accountManager = connection.getAccountManager();// 获取账户管理类
  12. } catch (XMPPException e) {
  13. throw new IllegalStateException(e);
  14. }
  15. connection.login("shimiso", "123","SmackTest");
  16. OfflineMessageManager offlineManager = new OfflineMessageManager(
  17. connection);
  18. try {
  19. Iterator<org.jivesoftware.smack.packet.Message> it = offlineManager
  20. .getMessages();
  21. System.out.println(offlineManager.supportsFlexibleRetrieval());
  22. System.out.println("离线消息数量: " + offlineManager.getMessageCount());
  23. Map<String, ArrayList<Message>> offlineMsgs = new HashMap<String, ArrayList<Message>>();
  24. while (it.hasNext()) {
  25. org.jivesoftware.smack.packet.Message message = it.next();
  26. System.out
  27. .println("收到离线消息, Received from 【" + message.getFrom()
  28. + "】 message: " + message.getBody());
  29. String fromUser = message.getFrom().split("/")[0];
  30. if (offlineMsgs.containsKey(fromUser)) {
  31. offlineMsgs.get(fromUser).add(message);
  32. } else {
  33. ArrayList<Message> temp = new ArrayList<Message>();
  34. temp.add(message);
  35. offlineMsgs.put(fromUser, temp);
  36. }
  37. }
  38. // 在这里进行处理离线消息集合......
  39. Set<String> keys = offlineMsgs.keySet();
  40. Iterator<String> offIt = keys.iterator();
  41. while (offIt.hasNext()) {
  42. String key = offIt.next();
  43. ArrayList<Message> ms = offlineMsgs.get(key);
  44. for (int i = 0; i < ms.size(); i++) {
  45. System.out.println("-->" + ms.get(i));
  46. }
  47. }
  48. offlineManager.deleteMessages();
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. offlineManager.deleteMessages();//删除所有离线消息
  53. Presence presence = new Presence(Presence.Type.available);
  54. nnection.sendPacket(presence);//上线了
  55. nnection.disconnect();//关闭连接

运行结果:

这里我们需要特别当心的是先不要告诉openfire服务器你上线了,否则永远也拿不到离线消息,用下面英文大概意思就是在你上线之前去获取离线消息,这么设计是很有道理的。

The OfflineMessageManager helps manage offline messages even before the user has sent an available presence. When a user asks for his offline messages before sending an available presence then the server will not send a flood with all the offline messages when the user becomes online. The server will not send a flood with all the offline messages to the session that made the offline messages request or to any other session used by the user that becomes online.

拿到离线消息处理完毕之后删除离线消息offlineManager.deleteMessages() 接着通知服务器上线了。

(5)下面我们来看看如何来发送文件

  1. PPConnection.DEBUG_ENABLED = false;
  2. AccountManager accountManager;
  3. final ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
  4. "192.168.1.78", Integer.parseInt("5222"), "csdn.shimiso.com");
  5. // 允许自动连接
  6. connectionConfig.setReconnectionAllowed(true);
  7. connectionConfig.setSendPresence(true);
  8. Connection connection = new XMPPConnection(connectionConfig);
  9. try {
  10. connection.connect();// 开启连接
  11. accountManager = connection.getAccountManager();// 获取账户管理类
  12. } catch (XMPPException e) {
  13. throw new IllegalStateException(e);
  14. }
  15. connection.login("admin", "admin","Rooyee");
  16. Presence pre = connection.getRoster().getPresence("shimiso@csdn.shimiso.com");
  17. System.out.println(pre);
  18. if (pre.getType() != Presence.Type.unavailable) {
  19. // 创建文件传输管理器
  20. FileTransferManager manager = new FileTransferManager(connection);
  21. // 创建输出的文件传输
  22. OutgoingFileTransfer transfer = manager
  23. .createOutgoingFileTransfer(pre.getFrom());
  24. // 发送文件
  25. transfer.sendFile(new File("E:\\Chrysanthemum.jpg"), "图片");
  26. while (!transfer.isDone()) {
  27. if (transfer.getStatus() == FileTransfer.Status.in_progress) {
  28. // 可以调用transfer.getProgress();获得传输的进度 
  29. System.out.println(transfer.getStatus());
  30. System.out.println(transfer.getProgress());
  31. System.out.println(transfer.isDone());
  32. }
  33. }
  34. }

运行结果:

在这里我们需要特别注意的是,跨资源是无法发送文件的,看connection.login("admin", "admin","Rooyee");这个代码就明白了,必须是“域名和资源名”完全相同的两个用户才可以互发文件,否则永远都没反应,如果不清楚自己所用的客户端的资源名,可以借助前面提到的SmackDebug工具查看往返信息完整报文,在to和from中一定可以看到。

如果我们自己要写文件接收例子的话,参考代码如下:

  1. FileTransferManager transfer = new FileTransferManager(connection);
  2. transfer.addFileTransferListener(new RecFileTransferListener());
  3. public class RecFileTransferListener implements FileTransferListener {
  4. public String getFileType(String fileFullName) {
  5. if (fileFullName.contains(".")) {
  6. return "." + fileFullName.split("//.")[1];
  7. } else {
  8. return fileFullName;
  9. }
  10. }
  11. @Override
  12. public void fileTransferRequest(FileTransferRequest request) {
  13. System.out.println("接收文件开始.....");
  14. final IncomingFileTransfer inTransfer = request.accept();
  15. final String fileName = request.getFileName();
  16. long length = request.getFileSize();
  17. final String fromUser = request.getRequestor().split("/")[0];
  18. System.out.println("文件大小:" + length + "  " + request.getRequestor());
  19. System.out.println("" + request.getMimeType());
  20. try {
  21. JFileChooser chooser = new JFileChooser();
  22. chooser.setCurrentDirectory(new File("."));
  23. int result = chooser.showOpenDialog(null);
  24. if (result == JFileChooser.APPROVE_OPTION) {
  25. final File file = chooser.getSelectedFile();
  26. System.out.println(file.getAbsolutePath());
  27. new Thread() {
  28. public void run() {
  29. try {
  30. System.out.println("接受文件: " + fileName);
  31. inTransfer
  32. .recieveFile(new File(file
  33. .getAbsolutePath()
  34. + getFileType(fileName)));
  35. Message message = new Message();
  36. message.setFrom(fromUser);
  37. message.setProperty("REC_SIGN", "SUCCESS");
  38. message.setBody("[" + fromUser + "]发送文件: "
  39. + fileName + "/r/n" + "存储位置: "
  40. + file.getAbsolutePath()
  41. + getFileType(fileName));
  42. if (Client.isChatExist(fromUser)) {
  43. Client.getChatRoom(fromUser)
  44. .messageReceiveHandler(message);
  45. } else {
  46. ChatFrameThread cft = new ChatFrameThread(
  47. fromUser, message);
  48. cft.start();
  49. }
  50. } catch (Exception e2) {
  51. e2.printStackTrace();
  52. }
  53. }
  54. }.start();
  55. } else {
  56. System.out.println("拒绝接受文件: " + fileName);
  57. request.reject();
  58. Message message = new Message();
  59. message.setFrom(fromUser);
  60. message.setBody("拒绝" + fromUser + "发送文件: " + fileName);
  61. message.setProperty("REC_SIGN", "REJECT");
  62. if (Client.isChatExist(fromUser)) {
  63. Client.getChatRoom(fromUser).messageReceiveHandler(message);
  64. } else {
  65. ChatFrameThread cft = new ChatFrameThread(fromUser, message);
  66. cft.start();
  67. }
  68. }
  69. /*
  70. * InputStream in = inTransfer.recieveFile();
  71. *
  72. * String fileName = "r"+inTransfer.getFileName();
  73. *
  74. * OutputStream out = new FileOutputStream(new
  75. * File("d:/receive/"+fileName)); byte[] b = new byte[512];
  76. * while(in.read(b) != -1) { out.write(b); out.flush(); }
  77. *
  78. * in.close(); out.close();
  79. */
  80. } catch (Exception e) {
  81. e.printStackTrace();
  82. }
  83. System.out.println("接收文件结束.....");
  84. }
  85. }

(6)用户列表

  1. **
  2. * 返回所有组信息 <RosterGroup>
  3. *
  4. * @return List(RosterGroup)
  5. */
  6. public static List<RosterGroup> getGroups(Roster roster) {
  7. List<RosterGroup> groupsList = new ArrayList<RosterGroup>();
  8. Collection<RosterGroup> rosterGroup = roster.getGroups();
  9. Iterator<RosterGroup> i = rosterGroup.iterator();
  10. while (i.hasNext())
  11. groupsList.add(i.next());
  12. return groupsList;
  13. }
  14. /**
  15. * 返回相应(groupName)组里的所有用户<RosterEntry>
  16. *
  17. * @return List(RosterEntry)
  18. */
  19. public static List<RosterEntry> getEntriesByGroup(Roster roster,
  20. String groupName) {
  21. List<RosterEntry> EntriesList = new ArrayList<RosterEntry>();
  22. RosterGroup rosterGroup = roster.getGroup(groupName);
  23. Collection<RosterEntry> rosterEntry = rosterGroup.getEntries();
  24. Iterator<RosterEntry> i = rosterEntry.iterator();
  25. while (i.hasNext())
  26. EntriesList.add(i.next());
  27. return EntriesList;
  28. }
  29. /**
  30. * 返回所有用户信息 <RosterEntry>
  31. *
  32. * @return List(RosterEntry)
  33. */
  34. public static List<RosterEntry> getAllEntries(Roster roster) {
  35. List<RosterEntry> EntriesList = new ArrayList<RosterEntry>();
  36. Collection<RosterEntry> rosterEntry = roster.getEntries();
  37. Iterator<RosterEntry> i = rosterEntry.iterator();
  38. while (i.hasNext())
  39. EntriesList.add(i.next());
  40. return EntriesList;
  41. }

(7)用户头像的获取

使用VCard,很强大,具体自己看API吧,可以看看VCard传回来XML的组成,含有很多信息的

  1. **
  2. * 获取用户的vcard信息
  3. * @param connection
  4. * @param user
  5. * @return
  6. * @throws XMPPException
  7. */
  8. public static VCard getUserVCard(XMPPConnection connection, String user) throws XMPPException
  9. {
  10. VCard vcard = new VCard();
  11. vcard.load(connection, user);
  12. return vcard;
  13. }
  14. /**
  15. * 获取用户头像信息
  16. */
  17. public static ImageIcon getUserImage(XMPPConnection connection, String user) {
  18. ImageIcon ic = null;
  19. try {
  20. System.out.println("获取用户头像信息: "+user);
  21. VCard vcard = new VCard();
  22. vcard.load(connection, user);
  23. if(vcard == null || vcard.getAvatar() == null)
  24. {
  25. return null;
  26. }
  27. ByteArrayInputStream bais = new ByteArrayInputStream(
  28. vcard.getAvatar());
  29. Image image = ImageIO.read(bais);
  30. ic = new ImageIcon(image);
  31. System.out.println("图片大小:"+ic.getIconHeight()+" "+ic.getIconWidth());
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. return ic;
  36. }

(8)组操作和用户分组操作

  1. **
  2. * 添加一个组
  3. */
  4. public static boolean addGroup(Roster roster,String groupName)
  5. {
  6. try {
  7. roster.createGroup(groupName);
  8. return true;
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. return false;
  12. }
  13. }
  14. /**
  15. * 删除一个组
  16. */
  17. public static boolean removeGroup(Roster roster,String groupName)
  18. {
  19. return false;
  20. }
  21. /**
  22. * 添加一个好友  无分组
  23. */
  24. public static boolean addUser(Roster roster,String userName,String name)
  25. {
  26. try {
  27. roster.createEntry(userName, name, null);
  28. return true;
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. return false;
  32. }
  33. }
  34. /**
  35. * 添加一个好友到分组
  36. * @param roster
  37. * @param userName
  38. * @param name
  39. * @return
  40. */
  41. public static boolean addUser(Roster roster,String userName,String name,String groupName)
  42. {
  43. try {
  44. roster.createEntry(userName, name,new String[]{ groupName});
  45. return true;
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. return false;
  49. }
  50. }
  51. /**
  52. * 删除一个好友
  53. * @param roster
  54. * @param userName
  55. * @return
  56. */
  57. public static boolean removeUser(Roster roster,String userName)
  58. {
  59. try {
  60. if(userName.contains("@"))
  61. {
  62. userName = userName.split("@")[0];
  63. }
  64. RosterEntry entry = roster.getEntry(userName);
  65. System.out.println("删除好友:"+userName);
  66. System.out.println("User: "+(roster.getEntry(userName) == null));
  67. roster.removeEntry(entry);
  68. return true;
  69. } catch (Exception e) {
  70. e.printStackTrace();
  71. return false;
  72. }
  73. }

(9)用户查询

  1. public static List<UserBean> searchUsers(XMPPConnection connection,String serverDomain,String userName) throws XMPPException
  2. {
  3. List<UserBean> results = new ArrayList<UserBean>();
  4. System.out.println("查询开始..............."+connection.getHost()+connection.getServiceName());
  5. UserSearchManager usm = new UserSearchManager(connection);
  6. Form searchForm = usm.getSearchForm(serverDomain);
  7. Form answerForm = searchForm.createAnswerForm();
  8. answerForm.setAnswer("Username", true);
  9. answerForm.setAnswer("search", userName);
  10. ReportedData data = usm.getSearchResults(answerForm, serverDomain);
  11. Iterator<Row> it = data.getRows();
  12. Row row = null;
  13. UserBean user = null;
  14. while(it.hasNext())
  15. {
  16. user = new UserBean();
  17. row = it.next();
  18. user.setUserName(row.getValues("Username").next().toString());
  19. user.setName(row.getValues("Name").next().toString());
  20. user.setEmail(row.getValues("Email").next().toString());
  21. System.out.println(row.getValues("Username").next());
  22. System.out.println(row.getValues("Name").next());
  23. System.out.println(row.getValues("Email").next());
  24. results.add(user);
  25. //若存在,则有返回,UserName一定非空,其他两个若是有设,一定非空
  26. }
  27. return results;
  28. }

(10)修改自身状态

包括上线,隐身,对某人隐身,对某人上线

  1. ublic static void updateStateToAvailable(XMPPConnection connection)
  2. {
  3. Presence presence = new Presence(Presence.Type.available);
  4. nnection.sendPacket(presence);
  5. public static void updateStateToUnAvailable(XMPPConnection connection)
  6. {
  7. Presence presence = new Presence(Presence.Type.unavailable);
  8. nnection.sendPacket(presence);
  9. }
  10. public static void updateStateToUnAvailableToSomeone(XMPPConnection connection,String userName)
  11. {
  12. Presence presence = new Presence(Presence.Type.unavailable);
  13. presence.setTo(userName);
  14. nnection.sendPacket(presence);
  15. }
  16. public static void updateStateToAvailableToSomeone(XMPPConnection connection,String userName)
  17. {
  18. Presence presence = new Presence(Presence.Type.available);
  19. presence.setTo(userName);
  20. nnection.sendPacket(presence);
  21. }

(11)心情修改

  1. **
  2. * 修改心情
  3. * @param connection
  4. * @param status
  5. */
  6. public static void changeStateMessage(XMPPConnection connection,String status)
  7. {
  8. Presence presence = new Presence(Presence.Type.available);
  9. presence.setStatus(status);
  10. connection.sendPacket(presence);
  11. }

(12)修改用户头像

有点麻烦,主要是读入图片文件,编码,传输之

  1. public static void changeImage(XMPPConnection connection,File f) throws XMPPException, IOException{
  2. VCard vcard = new VCard();
  3. vcard.load(connection);
  4. byte[] bytes;
  5. bytes = getFileBytes(f);
  6. String encodedImage = StringUtils.encodeBase64(bytes);
  7. vcard.setAvatar(bytes, encodedImage);
  8. vcard.setEncodedImage(encodedImage);
  9. vcard.setField("PHOTO", "<TYPE>image/jpg</TYPE><BINVAL>"
  10. + encodedImage + "</BINVAL>", true);
  11. ByteArrayInputStream bais = new ByteArrayInputStream(
  12. vcard.getAvatar());
  13. Image image = ImageIO.read(bais);
  14. ImageIcon ic = new ImageIcon(image);
  15. vcard.save(connection);
  16. }
  17. private static byte[] getFileBytes(File file) throws IOException {
  18. BufferedInputStream bis = null;
  19. try {
  20. bis = new BufferedInputStream(new FileInputStream(file));
  21. int bytes = (int) file.length();
  22. byte[] buffer = new byte[bytes];
  23. int readBytes = bis.read(buffer);
  24. if (readBytes != buffer.length) {
  25. throw new IOException("Entire file not read");
  26. }
  27. return buffer;
  28. } finally {
  29. if (bis != null) {
  30. bis.close();
  31. }
  32. }
  33. }

(13)用户状态的监听

即对方改变头像,状态,心情时,更新自己用户列表,其实这里已经有smack实现的监听器

  1. nal Roster roster = Client.getRoster();
  2. roster.addRosterListener(
  3. new RosterListener() {
  4. @Override
  5. public void entriesAdded(Collection<String> arg0) {
  6. // TODO Auto-generated method stub
  7. System.out.println("--------EE:"+"entriesAdded");
  8. }
  9. @Override
  10. public void entriesDeleted(Collection<String> arg0) {
  11. // TODO Auto-generated method stub
  12. System.out.println("--------EE:"+"entriesDeleted");
  13. }
  14. @Override
  15. public void entriesUpdated(Collection<String> arg0) {
  16. // TODO Auto-generated method stub
  17. System.out.println("--------EE:"+"entriesUpdated");
  18. }
  19. @Override
  20. public void presenceChanged(Presence arg0) {
  21. // TODO Auto-generated method stub
  22. System.out.println("--------EE:"+"presenceChanged");
  23. }
  24. });
 

SmackTest例子下载

基于xmpp openfire smack开发之smack类库介绍和使用[2]的更多相关文章

  1. 基于xmpp openfire smack开发之Android客户端开发[3]

    在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们着力介绍如何基于asmack开发一个Android的客户端,本篇的重点在实践,讲解和原理环节,大家可以参考前 ...

  2. iOS-iPad开发之SplitViewController简单介绍

    iOS-iPad开发之SplitViewController简单介绍 SplitViewController图形化创建 SplitViewController可以并列显示两个view,适用于基于nav ...

  3. iOS-iPad开发之popoverController使用介绍

    iOS-iPad开发之popoverController使用介绍 iOS开发UI篇-popoverController使用注意 iOS SDK:自定义Popover(弹出窗口) 实现的简单例子: // ...

  4. 基于xmpp openfire smack开发之openfire介绍和部署[1]

    前言 http://blog.csdn.net/shimiso/article/details/8816558 Java领域的即时通信的解决方案可以考虑openfire+spark+smack.当然也 ...

  5. Linux内核驱动开发之KGDB原理介绍及kgdboe方式配置

    接博文<Linux内核驱动开发之KGDB单步调试内核(kgdboc方式)>.上篇博文中,仅简单介绍使用串口的Kgbd的流程(kgdboc方式),本文将重点介绍KGDB调试Linux内核的原 ...

  6. Pilin —— 一个基于Xmpp openfire smack的即时聊天工具

    https://github.com/whfcomm/Pilin

  7. 8天掌握EF的Code First开发之Entity Framework介绍

    返回<8天掌握EF的Code First开发>总目录 本篇目录 Entity Framework概要 什么是ORM Entity Framework简史 Entity Framework具 ...

  8. 转载 8天掌握EF的Code First开发之Entity Framework介绍

    转载原地址:  http://www.cnblogs.com/farb/p/IntroductionToEF.html Entity Framework概要 Entity Framework是微软的O ...

  9. 测试开发之Django——No1.介绍以及引申

    前言 > 测试行业发展飞速,自动化测试兴起,由此对测试人员的要求与日俱增.随时而来的,就是职能的增加. > 首先需要学习的,就是自动化测试.而由自动化测试引申而来的,就是另外几个新增的岗位 ...

随机推荐

  1. 新增的output元素 progress元素 meter元素 keygen元素

    结果图 <output>是双标签 name:定义对象的唯一属性 for:定义输出域相关的一个或多个元素. form:定义所属的一个至多个表单. progress和meter一般和JS一起使 ...

  2. 一些static_cast const_cast

    static_cast:干杂活的,那三个都有各自的专有用途,那三个不做的都由这个转型符来做,只要它能做的,用C语法的强制类型转换运算符也一定能够完成:但话又说回来了,C强制类型转换能做的,它可不一定都 ...

  3. -Xms -Xmx -Xmn -Xss -XX:

    这两天遇到了pergen space的问题,在晚上查了查发现还挺普遍,并且通过eclipse启动,通过bat启动或者linux下通过sh启动,处理方式是不一样的,不过都是调整jvm的大小 如果有遇到同 ...

  4. 并发视频,怎么hold住高并发

    http://v.qq.com/boke/page/z/w/s/z0110e15rws.html http://weibo.com/codebox

  5. jquery deferred

    http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html http:// ...

  6. C#与C++、Java之比较概览

    转自C#与C++.Java之比较概览 C#与C++.Java之比较概览 Ben Albahari 著  荣耀 译 本文翻译时间较早.欢迎指出任何误失.谢谢. 感谢以下人士的支持和反馈(按字母先后顺序) ...

  7. 用了OneAPM CT,宕机早知道!

    Twitter 的公司网站和移动应用在 1 月 19 日早上出现宕机,导致全球部分地区用户无法正常访问.这次宕机影响了很多用户,英国和印度用户已经无法访问 Twitter .第三方监测机构 DownD ...

  8. LED七彩变色灯的制作

    LED变色灯是一种新型灯泡.它的外形与一般乳白色白炽灯泡相同,但点亮后会自动按一定的时间间隔变色.循环地发出青.黄.绿.紫.蓝.红.白色光.它适用于家庭生日派对.节日聚会.过节过年,给节日添加欢乐气氛 ...

  9. Delphi 类成员的默认访问权限(用RTTI检测)

    类的成员,如果没有private.public等显示什么,直接在class下面,没有写访问权限的限定符,这种成员是不是默认的访问权限啊?还是publish的访问权限啊? --------------- ...

  10. 加快AndroidStudio运行速度的方法

    之前用过其他人加速AndroidStudio构建速度的方法,确实在编译时有一定的效果 但是在实际使用中,随着项目越来越大,AndroidStudio有时还是会卡死,或者直接黑屏,我的笔记本是8g内存 ...