原文

Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。

Client A  发信息给 Client B ,  A的信息首先发送信息到服务器Server ,Server接受到信息后再把A的信息广播发送给所有的Clients

首先我们要在服务器建立一个ServerSocket ,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。

Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket

Server示例:

//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
//采用循环不断接受来自客户端的请求
while (true){
//每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
//下面就可以使用Socket进行通信了
...
}

客户端通常可使用Socket的构造器来连接到指定服务器
Client示例:

//创建连接到服务器、30000端口的Socket
Socket s = new Socket("192.168.2.214" , 30000);
//下面就可以使用Socket进行通信了
...

这样Server和Client就可以进行一个简单的通信了
当然,我们要做的是多客户,所以每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入clients集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务

//定义保存所有Socket的ArrayList
public static ArrayList<Socket> clients = new ArrayList<Socket>();

当服务器线程读到客户端数据之后,程序遍历clients集合,并将该数据向clients集合中的每个Socket发送一次。这样就可以实现一个聊天室的功能了

下面来看看整个功能的demo

先建立一个Java工程,把Server.java运行起来,然后再运行手机模拟器

服务器打印信息:

程序文件结构:

嘿嘿,大家别笑我,我的JAVA水平还是初学者,很多地方都觉得很菜,代码规格程度:小学。 有待提高啊!

1.先看看主Activity : SocketmsgActivity.java

public class SocketmsgActivity extends Activity {/** Called when the activity is first created. */private SQLiteDatabase db;Thread thread = null;Socket s = null;private InetSocketAddress isa = null; DataInputStream dis = null;DataOutputStream dos = null;private String reMsg=null;private Boolean isContect = false;private EditText chattxt;private EditText chatbox;private Button chatok;private String chatKey="SLEEKNETGEOCK4stsjeS";private String name=null,ip=null,port=null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);chattxt = (EditText)findViewById(R.id.chattxt);chatbox = (EditText)findViewById(R.id.chatbox);chatok = (Button)findViewById(R.id.chatOk);chatbox.setCursorVisible(false);chatbox.setFocusable(false);chatbox.setFocusableInTouchMode(false);chatbox.setGravity(2);//初始化,创建数据库来储存用户信息InitDatabase();db = SQLiteDatabase.openOrCreateDatabase(config.f, null);try {Cursor cursor = db.query("config", new String[]{"ip","name","port"},null,null, null, null, null);while(cursor.moveToNext()){name = cursor.getString(cursor.getColumnIndex("name"));ip = cursor.getString(cursor.getColumnIndex("ip"));port = cursor.getString(cursor.getColumnIndex("port"));}cursor.close();} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.toString());}db.close();//设置连接if(ip==null || port==null){Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();}//设置名称else if(name==null){Intent intent = new Intent(SocketmsgActivity.this,IniuserActivity.class);startActivity(intent);SocketmsgActivity.this.finish();}else{connect();chatok.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String str = chattxt.getText().toString().trim();System.out.println(s);try {dos.writeUTF(chatKey+"name:"+name+"end;"+str);chattxt.setText("");}catch (SocketTimeoutException  e) {System.out.println("連接超時,服務器未開啟或IP錯誤");Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blockSystem.out.println("連接超時,服務器未開啟或IP錯誤");Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();e.printStackTrace();}}});}}private Runnable doThread = new Runnable() {public void run() {System.out.println("running!");ReceiveMsg();}};   public void connect() {try {s = new Socket();isa = new InetSocketAddress(ip,Integer.parseInt(port)); s.connect(isa,5000); if(s.isConnected()){dos = new DataOutputStream (s.getOutputStream());dis = new DataInputStream (s.getInputStream());dos.writeUTF(chatKey+"online:"+name);/*** 这里是关键,我在此耗时8h+* 原因是 子线程不能直接更新UI* 为此,我们需要通过Handler物件,通知主线程Ui Thread来更新界面。* */thread = new Thread(null, doThread, "Message");thread.start();System.out.println("connect");isContect=true;}}catch (UnknownHostException e) {System.out.println("連接失敗");Toast.makeText(SocketmsgActivity.this, "連接失敗", Toast.LENGTH_SHORT).show();Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();e.printStackTrace();}catch (SocketTimeoutException  e) {System.out.println("連接超時,服務器未開啟或IP錯誤");Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();e.printStackTrace();}catch (IOException e) {System.out.println("連接失敗");e.printStackTrace();}}public void disConnect() {if(dos!=null){try {dos.writeUTF(chatKey+"offline:"+name);} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}try {s.close();} catch (IOException e) {e.printStackTrace();}}}/*** 线程监视Server信息*/private void ReceiveMsg() {if (isContect) {try {while ((reMsg = dis.readUTF()) != null) {System.out.println(reMsg);if (reMsg != null) {try {Message msgMessage = new Message();msgMessage.what = 0x1981;handler.sendMessage(msgMessage);Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}} catch (SocketException e) {// TODO: handle exceptionSystem.out.println("exit!");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/*** 通过handler更新UI*/Handler handler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 0x1981:chatbox.setText(chatbox.getText() + reMsg + '\n');chatbox.setSelection(chatbox.length());break;}}};@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();disConnect();//System.exit(0);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// TODO Auto-generated method stubmenu.add(0, 1, 1, "初始化設置");menu.add(0, 2, 2, "退出");return super.onCreateOptionsMenu(menu);}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// TODO Auto-generated method stubif(item.getItemId()==1){Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);startActivity(intent);SocketmsgActivity.this.finish();}else if(item.getItemId()==2){disConnect();SocketmsgActivity.this.finish();  android.os.Process.killProcess(android.os.Process.myPid());System.exit(0);}return super.onOptionsItemSelected(item);}public void InitDatabase(){if(!config.path.exists()){  config.path.mkdirs();    Log.i("LogDemo", "mkdir");  }   if(!config.f.exists()){      try{   config.f.createNewFile();  Log.i("LogDemo", "create a new database file");}catch(IOException e){   Log.i("LogDemo",e.toString());}   }  try {if(tabIsExist("config")==false){db = SQLiteDatabase.openOrCreateDatabase(config.f, null);  db.execSQL("create table config(_id integer primary key autoincrement," +"ip varchar(128),port varchar(10),name varchar(32))");Log.i("LogDemo", "create a database");db.close();}} catch (Exception e) {// TODO: handle exceptionLog.i("LogDemo",e.toString());}}/*** check the database is already exist* @param tabName* @return*/public boolean tabIsExist(String tabName){boolean result = false;if(tabName == null){return false;}Cursor cursor = null;db = SQLiteDatabase.openOrCreateDatabase(config.f, null); try {String sql = "select count(*) as c from sqlite_master where type ='table' " +"and name ='"+tabName.trim()+"' ";cursor = db.rawQuery(sql, null);if(cursor.moveToNext()){int count = cursor.getInt(0);if(count>0){result = true;}}} catch (Exception e) {// TODO: handle exception}  cursor.close();db.close();return result;}}

2.初始化IP和端口Activity, IniActivity.java

public class IniActivity extends Activity{private EditText ip,port;private Button nextButton;private String getip,getport;private ProgressDialog progressDialog;private InetSocketAddress isa = null; private SQLiteDatabase db;private String ipstring=null,portString=null;private int row=0;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.config);ip = (EditText)findViewById(R.id.ip);port = (EditText)findViewById(R.id.port);nextButton = (Button)findViewById(R.id.next);db = SQLiteDatabase.openOrCreateDatabase(config.f, null);try {Cursor cursor = db.query("config", new String[]{"ip","port"},null,null, null, null, null);while(cursor.moveToNext()){ipstring = cursor.getString(cursor.getColumnIndex("ip"));portString = cursor.getString(cursor.getColumnIndex("port"));row++;}ip.setText(ipstring);port.setText(portString);cursor.close();} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.toString());}db.close();nextButton.setOnClickListener(new nextButtonListenner());}class nextButtonListenner implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubgetip = ip.getText().toString().trim();getport = port.getText().toString().trim();if(getip=="" || getip==null || getip.equals("")){Toast.makeText(IniActivity.this, "請輸入IP", Toast.LENGTH_SHORT).show();ip.setFocusable(true);}else if(getport=="" || getport==null || getport.equals("")){Toast.makeText(IniActivity.this, "請輸入端口", Toast.LENGTH_SHORT).show();port.setFocusable(true);}else{//progressDialog = ProgressDialog.show(IniActivity.this, "", "請稍後...", true, false);//new Thread() {//@Override//public void run() {try {Socket s = new Socket();isa = new InetSocketAddress(getip,Integer.parseInt(getport)); s.connect(isa,5000); //showDialog("連接成功",IniActivity.this);try {//生成ContentValues对象ContentValues values = new ContentValues();//想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致values.put("ip", getip);values.put("port",getport);db = SQLiteDatabase.openOrCreateDatabase(config.f, null); if(row==0){db.insert("config", null, values);}else{db.update("config", values ,null,null);}Toast.makeText(IniActivity.this, "連接成功", Toast.LENGTH_SHORT);s.close();Intent intent = new Intent(IniActivity.this,IniuserActivity.class);startActivity(intent);IniActivity.this.finish();db.close();} catch (Exception e) {// TODO: handle exceptionshowDialog("設置失敗,數據庫不可用",IniActivity.this);}} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();showDialog("連接失敗,IP或者端口不可用",IniActivity.this);}catch (SocketTimeoutException  e) {System.out.println("連接超時,服務器未開啟或IP錯誤");showDialog("連接超時,服務器未開啟或IP錯誤",IniActivity.this);e.printStackTrace();}catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();showDialog("連接失敗,IP或者端口不可用",IniActivity.this);}//progressDialog.dismiss();//finish();//}//}.start();}}}/*** define a dialog for show the message* @param mess* @param activity*/public void showDialog(String mess,Activity activity){new AlertDialog.Builder(activity).setTitle("信息").setMessage(mess).setNegativeButton("確定",new DialogInterface.OnClickListener(){public void onClick(DialogInterface dialog, int which){          }}).show();}}

3.初始化用户名称Activity, IniuserActivity.java

public class IniuserActivity extends Activity{private EditText name;private Button ok;private SQLiteDatabase db;private String nameString;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.configuser);name = (EditText)findViewById(R.id.name);ok = (Button)findViewById(R.id.ok);ok.setOnClickListener(new okButtonListenner());db = SQLiteDatabase.openOrCreateDatabase(config.f, null);try {Cursor cursor = db.query("config", new String[]{"name"},null,null, null, null, null);while(cursor.moveToNext()){nameString = cursor.getString(cursor.getColumnIndex("name"));}name.setText(nameString);cursor.close();} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.toString());}db.close();}class okButtonListenner implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString getname = name.getText().toString().trim();if(getname==""){Toast.makeText(IniuserActivity.this, "請輸入您的稱呢", Toast.LENGTH_SHORT).show();name.setFocusable(true);}else{            try {//生成ContentValues对象ContentValues values = new ContentValues();//想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致values.put("name", getname);db = SQLiteDatabase.openOrCreateDatabase(config.f, null); db.update("config",values,null,null);Toast.makeText(IniuserActivity.this, "設置完成", Toast.LENGTH_SHORT).show();Intent intent = new Intent(IniuserActivity.this,SocketmsgActivity.class);startActivity(intent);IniuserActivity.this.finish();db.close();} catch (Exception e) {// TODO: handle exceptionshowDialog("設置失敗,數據庫不可用",IniuserActivity.this);}}}}/*** define a dialog for show the message* @param mess* @param activity*/public void showDialog(String mess,Activity activity){new AlertDialog.Builder(activity).setTitle("信息").setMessage(mess).setNegativeButton("確定",new DialogInterface.OnClickListener(){public void onClick(DialogInterface dialog, int which){          }}).show();}}

4.config.java

public class config{public static String SDCARD = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();public static File path = new File(SDCARD+"/RunChatDatabase/"); //数据库文件目录   public static File f = new File(SDCARD+"/RunChatDatabase/config.db"); //数据库文件
}

布局文件:

1.main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><EditText android:id="@+id/chatbox" android:layout_width="fill_parent"android:layout_height="fill_parent" android:layout_weight="1"></EditText><EditText android:id="@+id/chattxt" android:layout_width="fill_parent"android:layout_height="wrap_content" android:gravity="top"android:hint="你想和对方说点什么?"></EditText><Button android:id="@+id/chatOk" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="Send" android:textSize="@dimen/btn1"></Button></LinearLayout>

2.config.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><EditText android:id="@+id/chatbox" android:layout_width="fill_parent"android:layout_height="fill_parent" android:layout_weight="1"></EditText><EditText android:id="@+id/chattxt" android:layout_width="fill_parent"android:layout_height="wrap_content" android:gravity="top"android:hint="你想和对方说点什么?"></EditText><Button android:id="@+id/chatOk" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="Send" android:textSize="@dimen/btn1"></Button></LinearLayout>

3.configuer.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><EditText android:id="@+id/chatbox" android:layout_width="fill_parent"android:layout_height="fill_parent" android:layout_weight="1"></EditText><EditText android:id="@+id/chattxt" android:layout_width="fill_parent"android:layout_height="wrap_content" android:gravity="top"android:hint="你想和对方说点什么?"></EditText><Button android:id="@+id/chatOk" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="Send" android:textSize="@dimen/btn1"></Button></LinearLayout>

style文件:dimens.xml

<?xml version="1.0" encoding="utf-8"?><resources>     <dimen name="h3">30dip</dimen> <dimen name="h2">40dip</dimen> <dimen name="btn1">30dip</dimen><dimen name="et1">25dip</dimen></resources>

最后是服务器文件:Server.java

import java.io.*;import java.net.*;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.*;import javax.sound.sampled.Port;import javax.swing.JOptionPane;public class Server {ServerSocket ss = null;private String getnameString=null;boolean started = false;List<Client> clients = new ArrayList<Client>();List<Info> infos = new ArrayList<Info>();public static void main(String[] args) {String inputport = JOptionPane.showInputDialog("請輸入該服務器使用的端口:");int port = Integer.parseInt(inputport);new Server().start(port);}public void start(int port) {try {ss = new ServerSocket(port);System.out.println("服務器啟動");started = true;} catch (BindException e) {System.out.println(" 端口已经被占用");System.exit(0);}catch (IOException e) {e.printStackTrace();}try {while (started) {Socket s = ss.accept();Client c = new Client (s);System.out.println("a client is connected");new Thread(c).start();clients.add(c);}} catch (IOException e) {e.printStackTrace();}finally {try {ss.close();} catch (IOException e) {e.printStackTrace();}}}public List<Client> getClient(){return clients;}class Client implements Runnable {private String chatKey="SLEEKNETGEOCK4stsjeS";private Socket s = null;private DataInputStream dis = null;private DataOutputStream dos = null;private boolean bConnected = false;private String sendmsg=null;Client (Socket s) {this.s = s;try {dis = new DataInputStream (s.getInputStream());dos = new DataOutputStream (s.getOutputStream());bConnected = true;} catch(IOException e) {e.printStackTrace();}}public void send (String str) {try {//System.out.println(s);dos.writeUTF(str+"");dos.flush();} catch(IOException e) {clients.remove(this);System.out.println("对方已经退出了");}}public void run() {try {while (bConnected) {String str = dis.readUTF();DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");String date = "  ["+df.format(new Date())+"]";if(str.startsWith(chatKey+"online:")){Info info = new Info();getnameString = str.substring(27);info.setName(getnameString);infos.add(info);for (int i=0; i<clients.size(); i++) {Client c = clients.get(i);c.send(getnameString+" on line."+date);}System.out.println(getnameString+" on line."+date);}else if(str.startsWith(chatKey+"offline:")){getnameString = str.substring(28);clients.remove(this);for (int i=0; i<clients.size(); i++) {Client c = clients.get(i);c.send(getnameString+" off line."+date);}System.out.println(getnameString+" off line."+date);}else{int charend = str.indexOf("end;");String chatString = str.substring(charend+4);String chatName = str.substring(25, charend);sendmsg=chatName+date+"\n"+chatString; for (int i=0; i<clients.size(); i++) {Client c = clients.get(i);c.send(sendmsg);}System.out.println(sendmsg);}}} catch (SocketException e) {System.out.println("client is closed!");clients.remove(this);} catch (EOFException e) {System.out.println("client is closed!");clients.remove(this);}catch (IOException e) {e.printStackTrace();}finally {try {if (dis != null) dis.close();if (dos != null) dos.close();if (s != null) s.close();} catch (IOException e) {e.printStackTrace();}}}}class Info{private String info_name = null;public Info(){}public void setName(String name){info_name = name;}public String getName(){return info_name;}}}

以上只是一个粗略的聊天室功能,如果要实现私聊,还需要保存该Socket关联的客户信息。一个客户端可以将信息发送另一个指定客户端。实际上,我们知道所有客户端只与服务器连接,客户端之间并没有互相连接。这个功能等我以后有时间再写个demo.....

转载于:https://www.cnblogs.com/peakzheng/archive/2012/02/05/2339137.html

【转】Android 基于Socket的聊天室相关推荐

  1. Android 基于Socket的聊天室

    原文地址为: Android 基于Socket的聊天室 Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路, ...

  2. 【python】基于Socket的聊天室Python开发

    基于Socket的聊天室Python开发 一.Socket简述 二.创建服务端Server 2.1 创建服务端初始化 2.2 监听客户端连接 2.3 处理客户端消息 三.创建客户端Client 3.1 ...

  3. 基于socket的聊天室实现原理

    基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室.这种聊天室的特点很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新.而是当有人发言时,屏幕上才会出现新聊天内容, ...

  4. Python语言基于Socket实现聊天室(包含登录、注册功能)

    一.聊天室的整体架构 1.twisted:实现服务端,以及事件驱动 Twisted是用Python实现的基于事件驱动的网络引擎框架. 2.socket:实现客户端,以及事件驱动 3.tkinter:实 ...

  5. 【java毕业设计】基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码)——聊天室系统

    基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+原生Sevlet+socket的聊天室系统设计与实现,文章末尾附有本毕业设 ...

  6. 基于WebSocket实现聊天室(Node)

    基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...

  7. Socket.IO聊天室~简单实用

    小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...

  8. SpringBoot + Vue 实现基于 WebSocket 的聊天室(单聊)

    前言 在前一篇文章SpringBoot 集成 STOMP 实现一对一聊天的两种方法中简单介绍了如何利用 STOMP 实现单聊,本文则将以一个比较完整的示例展示实际应用,不过本文并未使用 STOMP,而 ...

  9. 基于Python的聊天室

    基于Python的聊天室 文章目录 基于Python的聊天室 一.引言 1.1 背景和意义 1.2 系统要实现的功能 1.2.1 用户登录 1.2.2 群发消息 1.2.3 一对一聊天 1.2.4 发 ...

  10. 基于linux网络聊天室的设计,参考基于linux网络聊天室的设计.doc

    参考基于linux网络聊天室的设计 长沙理工大学<高级操作系统>课程设计报告学 院 计算机与通信工程 专 业 计算机科学与技术 班 级 学 号 学生姓名 指导教师 课程成绩 完成日期 课程 ...

最新文章

  1. c++ 继承访问控制初步
  2. 计算机专业python教材_计算机专业几本必看的书!
  3. Windows Mobile 获取基站信息(LAC,CellID)
  4. MyEclipse报错:String cannot be resolved to a type
  5. 第一章 DevOps概述
  6. 深度学习:网络的编程模式比较
  7. json java typeof_Json对象与Json字符串的转化、JSON字符串与Java对象的转换
  8. maccmsv10 苹果cms10 站群扩展 自用版
  9. 武德 | 年轻人!这才叫真正的程序猿的武德
  10. php上传文件测试代码,php 文件上传函数的超详细示例
  11. 华硕aura完全卸载_AURA神光同步是什么意思?AURA SYNC神光同步教程
  12. Newman定制报告
  13. 2021年第四届“安洵杯”网络安全挑战赛Writeup
  14. 计算机论文word版,计算机应用基础第05章Word高级应用-毕业论文排版
  15. 车牌检测(分别使用Haar级联 和轮廓裁剪)
  16. 好女人必看行为守则100条----男人也学学吧!
  17. 中国移动的5G套餐定价亲民,决心在5G时代争先
  18. CMD命令工具--Windows下使用tree命令生成目录
  19. java字符串差异比较工具类
  20. QGC地面站Mavlink生成和MockLink模拟收发通讯

热门文章

  1. 刺客信条奥德赛缺少dll文件_《刺客信条 奥德赛》免费归来,单人冒险暗杀游戏,搞一搞喽...
  2. 《高翔视觉slam十四讲》学习笔记 第六讲 非线性优化
  3. vue 异步更新队列 Vue.nextTick(callback)
  4. vue element ui 样式修改无效
  5. 力扣-64 最小路径和
  6. 二进制十进制间小数怎么转换
  7. Java学习之路 之 类篇
  8. 《Android开发艺术探索》— Android 书籍
  9. Eclipse中快速使代码对齐?1张图搞定!
  10. 7-4 用天平找小球 (10 分)