Android面试基础题总结一

字数 8040阅读 158

Android四大组件:

activity:

  1. activity的生命周期:activity是context的子类,同时实现了window.callback 和 keyevent.callback.可以处理与窗体用户交互的事件。activity从创建到销毁有多种状态,在这些状态转换的时候伴随有回调方法:onCreate(创建 ),onStart(可见),onResume(可交互),onPause(不可交互),onStop(不可见),onDestory(销毁),onRestart(重新可见).

    • activity在一创建的时候会执行onCreate(),onStart(),onResume(),在A界面上启动B界面的之后,A界面会执行onPause(),onStop()方法,如果B界面是一个diaLog,A界面处于可见但不可交互的状态,会执行onStop()方法,由B界面返回A界面会执行onReStart(),onstart(),onResume()方法,退出A界面会执行onPause(),onStop(),onDestory()方法。
  2. activity的几种启动模式:包括:标准模式(standard),singleTop,singleTask,singleInstance。

    • 标准启动模式是说:默认的启动模式,可以不用配置,会随着每个activity的开启,每次都会创建一个实例对象,可以有多个实例对象,也可以多个相同的activity叠加。在点击back退出时会依照栈顺序依次退出。
    • singleTop是说:可以有多个实例对象,但不可以多个相同activity叠加,如果activity在栈顶,启动相同的activity,不会创建新的实例,而会调用它的onNewIntent方法。
    • singleTask是说:只有一个实例对象,在同一个应用程序中启动它时,若该activity不存在,就会在当前的任务栈中创建一个新的实例,若存在,则会把任务栈中所有在其之上的activity全部destory之后再调用其onNewIntent方法。而如果说在其他的应用程序中启动它,则会新建一个task,并在该task中启动这个activity,singleTask允许别的activity与其在统一个task中共存,也就是说,如果我在这个singleTask的实例中在启动新的activity,这个新的activity还是会存在这一个singleTask的实例的任务栈中。
    • singleInstance是说:只有一个实例,并且这个实例只运行在一个task中,在这个task中只有这一个实例,不允许在有其他activity存在。
  3. 如何保存和恢复Activity的状态数据:

    • activity的状态通常情况下系统会自动保存,一般来说,在调用onPause()和onStop()方法之后,activity的实例仍然保存在内存中,activity的所有信息和状态数据都不会丢失,当activity重新回到前台之后,所有的改变都会保留,
    • 但是当系统内存不足时,调用onPause()和onStop()方法之后的activity可能会被系统销毁,此时内存中就没有了这个activity的实例对象了,如果这个activity重新回到前台,所有的改变都会消失,为了避免该情况的发生,可以覆写onsaveInstanceState()方法。onsaveInstanceState()方法接收一个bundle类型的参数,可以将状态数据存储在bundle中,这样即使activity销毁,用户在次启动activity,在调用它的onCreate(),上述的bundle对象会作为实参来传递给onCreate()方法,然后可以从bundle中获取到保存的数据,将activity恢复到销毁前的样子。需要注意的是调用onsaveInstanceState()方法,要在方法onPause()和onStop()调用之前。
  4. 两个activity之间跳转必然会执行那些方法;

    • 两个activity,从A跳转至B,当B是一个对话框时或者透明窗体时,A会调用onPause()方法,B会调用onCreate(),onStart(),onResume(),当B覆盖A时,A会调用onStop()方法。
  5. Android中activity,context,application之间有什么区别;

    • 相同点:context是描述一个应用程序环境的信息,即上下文的意思,该类是一个抽象类(abstract class),Android有提供该抽象类的具体实现类(contextlml),activity和application都是context的子类。
    • 不同点: 维护的生命周期不同。context维护的是当前activity的生命周期,而application维护的是整个项目的生命周期。
    • 在使用context的时候,需要防止内存泄漏,需要注意几点:
      • 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身的生命周期相同;
      • 对于生命周期长的使用application context;
      • 避免使用非静态内部类,尽量使用静态类,避免生命周期的问题,注意内部类对外部对象引用时导致的生命周期的变化。
  6. 如何退出activity?如何安全的退出已调用多个activity的application;

    • 通常退出一个activity只需要按返回键,代码中直接调用finish()方法就行,

    • 用数组记录住打开的每一个activity,在需要退出的时候,遍历,调用finish()方法关闭每一个activity即可。

    • 发送特定的广播
      在需要结束应用时,发送一个特定的广播,每个Activity 收到广播后,关闭即可。
      //给某个activity 注册接受接受广播的意图
      registerReceiver(receiver, filter)
      //如果过接受到的是关闭activity 的广播就调用finish()方法把当前的activity finish()掉

    • 递归退出。在打开新的Activity时使用startActivityForResult,然后自己添加标志,在onActivityResult()中处理,递归关闭。

  7. 两个activity之间如何传递数据;

    • 传递的方式有:intent,广播接收者,contentProvider,static静态数据(public static 成员变量),file文件存储,sharedPreferences,sqlite数据库.

service:

  1. service是在main方法中执行,service中能否执行耗时操作;

    • 默认情况下,如果没有显示的是指service所运行的进程,service和activity是运行在当前APP所在进程的主线程(main thread)中,service中不能进行耗时操作(网络操作,拷贝数据库,大文件),
    • 特殊情况下,可以在清单文件中进行配置service所执行的进程,让service在其他进程中执行。
  2. activity怎样和service绑定,怎样在activity中启动对应的service;

    • activity通过bindService(intent service,ServiceConnection conn,int flags)跟service进行绑定,当绑定成功之后,service会将代理对象通过回调的方式传递给conn,这样就可以拿到Service提供的代理对象了。一般情况下, 如果想获取Service的服务对象那么就需要通过bindService(),比如,音乐播放器,第三方支付。
    • activity还可以通过startService(),通常仅需要开启一个后台任务的时候用startService()。
  3. service的生命周期;

    • service有绑定模式和非绑定模式,以及两种的混合模式,不同的模式生命周期不同;
      • 非绑定模式:当第一次调用startService的时候执行onCreate(),onStartCommand(),当service关闭的时候执行onDestory();
      • 绑定模式:当第一次调用bindService()的时候,执行onCreate(),onBind(),当解除绑定的时候执行onUnbind(),onDestory()。
      • 还需要注意的是service实例只会有一个,也就是说如果当前要启动的service已经存在了,那就不需用在启动service了,也就不会在调用onCreate()方法了。
      • 一个service被多个客户所绑定,只有所有的绑定对象都执行了onBind()方法后该service才会销毁,但是如果有一个客户执行了onStart()方法,那么这个时候即使所有的service都执行了onBind()方法,service也不会销毁。
  4. 什么是IntentService?有什么优点?

    • intentService是service的子类,比起普通的service有了新的功能。普通的service存在两个问题:service不会启动一条单独的线程,service与他所在的应用位于同一个进程中;不能在service中直接处理耗时操作。
    • intentService的特征:会创建独立的worker线程来处理所有的intent请求;会创建独立worker线程来处理onHandlerIntent()方法实现的代码,无需处理多线程问题;所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法来停止Service;为service的onBind()方法提供默认的实现,返回null;为service的onStartCommard()方法提供默认实现,将请求intent添加到请求队列中。
  5. activity,service,intent之间的关系?

    • activity负责用户界面的显示和交互,Service负责后台任务的处理,activity和service之间通过intent传递数据,activity和service都是context的子类contextWrapper的子类。
  6. service中可以谈吐司吗?

    • 可以的,但是得有个条件就是得有一个context上下文,由于service是context的子类,因此谈吐司是可以的。比如在service中完成任务的下载之后弹一个土司来提醒一下用户是完全可以的。
  7. service有哪些启动方法。有什么区别,怎样停用service?

    • 通过startService()方法,service启动之后会调用onCreate(),onStart()方法处于运行状态,stopService的时候调用onDestory()方法停止服务,而如果调用者自己直接退出而没有调用stopService的方法时,service会一直运行在后台。
    • 通过bindService()方法,service启动后回调用onCreate()方法,然后调用onBind()方法,这个时候调用者会和service绑定在一起,如果调用者退出了,service就会调用onUnbind(),onDestory()方法退出。调用者也可以调用unbindService()来停止服务。
    • 需要注意的原则:service的onCreate()方法只会被调用一次,就是无论多少次的startService或者bindService,service只会被创建一次。
    • 如果service在运行期间调用了bindService,这时候在调用stopService,service是不会调用onDestory方法的,service就停止不了了。只有在调用了UnbindService之后,service才会被销毁。
    • 如果一个service通过startService被start之后,多次调用startService方法的话,这个时候会多次调用onStart方法,多次的调用stopService方法,但是onDestory方法只会被调用一次。
    • 如果一个service通过bindService被start之后,多次调用bindService方法的话,service之后调用一个onBind方法,多次调用unbindService方法会抛异常。

broadcast receiver:

  1. 什么是broadcast receiver,生命周期是什么?

    • broadCast receiver 广播接收者,分为有序和无序,内部实现机制是通过Android系统的binder机制实现通信的。
    • 无序广播:完全异步,逻辑上是可以被任何的广播接收者接收到,效率较高,但是无法一个接受者不能将处理结果传递给下一个接受者,并无法终止广播intent的传播。
    • 有序广播:按照被接受者的优先级顺序,在被接受者中依次传播。
  2. 在mainfast和代码中如何注册和使用broadcast receiver。

    • 静态注册:在mainfast.xml文件中注册。静态注册的广播,只要应用一直在系统中运行就会一直接收到广播信息。

        <receiver android:name=".BroadcastReceiver1" >
        <intent-filter>
        <action android:name="android.intent.action.CALL" >
        </action>
        </intent-filter>
        </receiver>
      
    • 动态注册:在代码中注册。动态注册的的广播,当注册的activity或者service销毁了,就接收不到广播了。

        receiver = new BroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(CALL_ACTION);
        context.registerReceiver(receiver, intentFilter);
      
  3. broadcastReceiver的生命周期;

    • 广播接受者的生命周期很短暂,在接收到广播的时候创建,onReceive()方法结束之后销毁。
    • 广播接收者中不要做一些耗时操作,否则会引起ANR,耗时较长的最好放在service中进行。
    • 最好不要再广播接收者中创建子线程做耗时操作,因为广播接收者被销毁之后,进程就变成了空进程,很容易被系统清理掉。

contentProvider :

  1. contentProvider是如何实现数据共享的?

    • contentProvider是应用程序见间共享数据的接口,使用的话需要先自定义一个类继承ContentProvider,然后覆写实现query,insert,update,delete四个方法。好需要在清单文件中进行注册。

        public class PersonContentProvider extends ContentProvider{
        public boolean onCreate(){
            }
            query(Uri, String[], String, String[], String);
            insert(Uri, ContentValues);
            update(Uri, ContentValues, String, String[]);
            delete(Uri, String, String[]);
        }
      
  2. Android中的数据存储的方式?

    • file文件,sharedPreference,conteneProvider,SQLite数据库,网络存储。
  3. 说出contentProvider,contentResolver, contentObserver之间的关系?

    • contentProvider,内容提供者,用于对外提供数据;
    • contentResolver,内容解析者,用于获取内容提供者提供的数据;contentResolver.notifyChange(uri)发出消息。
    • contentObserver,内容观察者,用于监听内容数据的改变主状态。contentResolver.registercontentObserver()监听消息。
  4. contentObserver内容观察者的作用及特点?

    • contentObserver目的是观察特定的uri引起的数据库的变化。继而做一些相应的处理。
    • 观察特定的uri的步骤:
      • 创建特定的contentObserver派生类,必须重载父类的构造方法,必须重载onChange()方法去处理回调后的功能实现。
      • 利用context.getContentResolover()获取contentResolover对象,接着调用registerContentObserver()方法去注册内容观察者;
      • 在不需要时,需要手动的调用unregisterContentObserver()去取消注册。

intent:

  1. intent传递数据可以传递那些类型数据?

    • 八大基本数据类型和String以及数组形式都可以,还可以传递实现了Serializable和Parcelable接口的对象。
  2. 描述intent和intentFliter是什么?

    • Android中通过intent对象来表示一条消息,通过intent可以实现各种系统组件的调用和激活。
    • intentFliter可以理解为一个邮局或者一个信笺的分拣系统。

listview:

  1. listview的优化方式;
    • 复用convertView,优化加载布局,如果没有缓存就加载布局,如果有缓存就直接使用conventView对象,这样在滑动listview的时候就不用每次都去调用gitView()方法去加载布局了。

    • 使用自定义静态类viewHolder,减少fingviewById的次数,convertView为空的时候,viewHolder会将空间里的实例存放在viewHolder中,然后用setTag()的方法将viewHolder对象存放在view中。conventView不为空的时候,用getTag()的方法获取viewHolder对象。

        public View getView(int position, View convertView, ViewGroup parent) {
           Log.d("MyAdapter", "Position:" + position + "---"
                   + String.valueOf(System.currentTimeMillis()));
           ViewHolder holder;
           if (convertView == null) {
               final LayoutInflater inflater = (LayoutInflater) mContext
                      .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
               convertView = inflater.inflate(R.layout.list_item_icon_text, null);
               holder = new ViewHolder();
               holder.icon = (ImageView) convertView.findViewById(R.id.icon);
               holder.text = (TextView) convertView.findViewById(R.id.text);
               convertView.setTag(holder);
           } else {
               holder = (ViewHolder) convertView.getTag();
           }
           holder.icon.setImageResource(R.drawable.icon);
           holder.text.setText(mData[position]);
           return convertView;
        }
        
        static class ViewHolder {
           ImageView icon; 
           TextView text;
        }
      
    • 异步加载数据,分页加载数据;

      • listview的分页加载, 设置listview的滚动监听器,setOnScrollListener(new OnScrollListener { ... });该监听器有两个方法,onScrollStateChanged()--滚动状态发生改变的时候,onScroll()0--listview被滚动时调用的方法。在滚动状态发生改变的时候,有三种状态:

        • 手指按下移动的状态:SCROLL_STATE_TOUCH_SCROLL :触摸滑动。
        • 惯性滚动状态:SCROLL_STATE_FLING : (滑翔 )
        • 静止状态:SCROLL_STATE_IDLE : 静止。
      • 对不同的状态进行处理:分批加载数据,只关心静态状态:关心最后一个可见的条目,如果最后一个可见条目就是适配器里的最后一个,此时就可加载更多的数据,在每次加载的时候, 计算出滚动的数量,当滚动的数量大于等于总数量的时候,可以提示用户无更多的数据。

  1. listview数据集改变之后,如何更新listview?

    • 使用listview的adapter的notifyDataSetChange()方法,该方法会使listview重新绘制。
  2. listview能否实现多种类型的条目?

    • 可以,listview显示的每个条目都是通过baseAdapter的gitView(int position,View convertView,ViewGroup parent)来展示的,理论上可以让每个条目都是不同类型的view。
    • 另外,adapter还提供了getViewTypeCount()和getItemViewType(int position)两个方法,在getView方法中可以根据不同的viewtype加载不同的布局文件。
  3. listview如何跳转到指定位置?

    • 可以通过lv.setSelection(listView.getPosition)方法。
  4. listview如何优化图片?图片错乱的问题是如何产生的;

    • 图片处理的方法有以下几种:

      • 不要直接拿路径去循环,BitmapFactory.decodeFile,使用Options保存图片大小,不要加载图片到内存中去。
      • 对图片一定要边界压缩,尤其是大图,而如果图片是后台服务器处理好的就不用了。
      • 在listview中取图片的时候不要直接拿路径去取,而是使用lruCache对图片做缓存处理;
      • 在getView中做图片转换的时候,产生的中间变量一定要释放。
    • 图片错乱的原因分析: 图片错乱的本质是由于在listview的时候使用了缓存ConvertView导致的,假设一种场景,一个listview一屏只能显示十条item,那么在拉出第11条item的时候,这条item其实是复用的第一条item,也就是说第一条item从服务端下载的图片,并最重要显示的时候,其实该item已经不再当前显示的区域内了,此时显示的结果可能在第11条item上输出图像,这就导致了图片错乱的问题。解决的方案就是通过给图片设置tag来防止图片错乱。在getView的时候,给viewHolder类中的imageView设置一个Tag,这个tag设置的是图片的url地址,然后在异步加载图片完成回调的方法中,使用findviewWithTag(String url)来找到listview中position对应的imageview。然后给imageview设置图片即可。前提需要预设一张图片。

         //给imageView设置一个tag。
         holder.img.setTag(imgUrl);  
         // 预设一个图片  
         holder.img.setImageResource(R.drawable.ic_launcher);  
         if (imgUrl != null && !imgUrl.equals("")) {  
             Bitmap bitmap = imageLoader.loadImage(holder.img, imgUrl,  
                     new ImageDownloadedCallBack() {  
      
                        @Override  
                         public void onImageDownloaded(ImageView imageView,  
                                 Bitmap bitmap) {  
                             // 通过 tag 来防止图片错位  
                             if (imageView.getTag() != null  
                                     && imageView.getTag().equals(imgUrl)) {  
                                 imageView.setImageBitmap(bitmap);  
                            }  
                        }  
                     });  
             if (bitmap != null) {  
                 holder.img.setImageBitmap(bitmap);  
             }  
         }  
      
  5. scrollView中如何嵌套listview;

    • 通常情况下,在scrollView 重视不嵌套listview的,但是面试官要是问到这种问题的时候,回答是可以的,在scrollview 中添加一个listview会导致listview控件显示不全,通常只会显示一条,这是由于两个控件的滑动冲突导致的,所以:
      • 需要通过listview的item数量去计算listview的显示高度,从而使其完整显示;
      •   lv = (ListView) findViewById(R.id.lv);
          adapter = new MyAdapter();
          lv.setAdapter(adapter);
          setListViewHeightBasedOnChildren(lv);
          ----------------------------------------------------
          public void setListViewHeightBasedOnChildren(ListView listView) {
          ListAdapter listAdapter = listView.getAdapter();
          if (listAdapter == null) {
          return;
          }
          int totalHeight = 0;
          for (int i = 0; i < listAdapter.getCount(); i++) {
          View listItem = listAdapter.getView(i, null, listView);
          listItem.measure(0, 0);
          totalHeight += listItem.getMeasuredHeight();
          }
          ViewGroup.LayoutParams params = listView.getLayoutParams();
          params.height = totalHeight + (listView.getDividerHeight() *
          (listAdapter.getCount() - 1));
          params.height += 5; //如果没有这个声明,listview就只有一点。
          
          listView.setLayoutParams(params);
          }
          
          //而现阶段最好的方法就是自定义listview,重写OnMeasure( )方法,使其完整显示。
          
          public class ScrollViewWithListView extends ListView {
          public ScrollViewWithListView(android.content.Context context,
          android.util.AttributeSet attrs) {
          super(context, attrs);
          }
          /**
          * Integer.MAX_VALUE >> 2,如果不设置,系统默认设置是显示两条
          */
          public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
          MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
           }
          }
        
  6. 如何刷新listview中item的单个数据,不刷新整个listview的数据?

    • 修改单个item的数据,然后调用adapter的notifyDataSetChanged()方法进行刷新。或者直接用handler去更新,在adapter中创建一个handler,值发生改变的时候,handler就send一个message,更新ui。

recyclerView:

  1. 使用recycleView的好处;

    • recycleView是Android 5.0 materials design 中的组件之一,recycleView封装了viewHolder的回收复用机制,也就是说recycleView标准化了viewHolder,编写Adapter面向的是viewHolder而不再是view了,复用的逻辑被封装了,写起来更方便了。recycleView提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecylerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还有StaggeredGridLayoutManager等),也就是说RecylerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。你想控制Item的分隔线,可以通过继承RecylerView的ItemDecoration这个类,然后针对自己的业务需求去抒写代码。
      可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecylerView有其自己默认的实现。
  2. recycleView的使用方法:

      recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            LinearLayoutManager layoutManager = new LinearLayoutManager(this );
            //设置布局管理器
            recyclerView.setLayoutManager(layoutManager);
            //设置为垂直布局,这也是默认的
            layoutManager.setOrientation(OrientationHelper. VERTICAL);
            //设置Adapter
            recyclerView.setAdapter( recycleAdapter);
            //设置分隔线
            recyclerView.addItemDecoration(new DividerGridItemDecoration(this ));
            //设置增加或删除条目的动画
            recyclerView.setItemAnimator( new DefaultItemAnimator());
    
  3. recylerView的Adapter的写法,需要实现三个方法:

    • onCreateViewHolder():这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
    • onBindViewHolder():这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
    • getItemCount():这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。
  4. 给RecyclerView的Item添加点击事件:

    • 由于recylerView没有提供类似于listview的setOnItemClickListener()的方法来处理item的点击事件,因此只能模拟类似的方法, 使用的是在创建itemView的时候添加监听,就是在创建view的时候添加点击事件,然后在Adapter对对象中添加监听回调. 具体的做法是:首先自定义接口onRecylerViewItemClickListener,定义onItemClick()方法,在给方法中有两个参数,view和position,在给holder传入onRecylerViewItemClickListener参数,让holder实现View.OnClickListener,并在onClick方法中调用onRecylerViewItemClickListener.onItemClick()方法,通过传入的position来判断item的位置,从而实现每个item的点击事件.
  5. 给RecyclerView的Item添加下拉刷新:

    • 通过SwipeRefreshLayout这个组件,去实现列表下拉刷新功能,通过设置下拉刷新的监听事件setOnRefreshListener()重写OnRefresh()方法,而设置上拉加载更多可以通过设置滑动事件监听来实现setOnScrollListener()重写onScrollStateChanged()方法.通过设置swipeRefreshView.setRefreshing为true来实现刷新.

socket通信与网络编程(TCP/UDP协议,http协议)

  1. 什么是网络编程:

    • 网络编程是指两台设备之间实现数据传递的过程,也可以说是使用套接字完成不同进程之间的网络通讯的编程。要了解网络编程,需要先了解网络通讯,网络通讯分HTTP通讯和socket网络通讯,说到这需要先了解一下网络通讯的层级,网络通讯的层级一共有四层:最低层链路层,这里主要是硬件的接口,然后是网络层,这里用我们比较熟悉的IP协议,在然后是传输层,这里有TCP协议和UDP协议,最后就是应用层,HTTP协议(超文本传输协议)就在这一层,这里需要注意的是,HTTP是一种协议,而socket是一个接口。
  2. 传输层两大协议:TCP/UDP协议:

    • UDP协议是一种用户数据报协议,是面向无连接的,数据传输不可靠的一种点对多点的通讯,也就是说UDP在传输数据前是不与对方建立连接的,对于接收到的数据也是不发送确认信号的,发送数据的一方也不会知道数据是否发送成功,也就无法再重新发送了。我们经常使用的“ping”命令来检测两台设备主机之间的TCP/IP通信是否正常,而这个“ping”就是 使用UDP协议,通过向对方主机发送UDP数据包,然后对方确认收到数据包,如果对方将数据包到达的纤细及时的返回回来,就说明两台设备主机之间的通讯是通的。
    • TCP协议是一种传输控制协议,它是面向有连接的,数据传输可靠的一种通讯方式,它是通过三次握手来实现面向有连接的,而这三次握手指的是:
  1. 首先客户端发送一个空的数据报包给服务端,并且将客户端置为发送状态;
  2. 接着服务端接收到这这个空的数据报包,会相应客户端一个确认包,并将服务端置为接收状态;
    3)客户端接收到服务端发送回来的响应,然后再向服务端发送一个确认包,一旦此包发送完毕,那么服务端就与客户端之间建立了长连接,并且双方都处于确认状态,而建立的这个长连接在理论上如果单方不主动去停止这个连接,这个连接就会一直存在,只要连接存在,服务器就可以和客户端近行数据的互传。
  1. 什么是socket通信:

    • 说起socket,得要先知道套接字,套接字是TCP/IP网络通信的基本操作单元,主要包括三大要素:IP,协议,端口。在说socket,socket其实就是一堆套接字,它在客户端叫clientSocket,在服务端叫serviceSocket,socket其实就是方便TCP和UDP编程的一个接口,应用层和传输层通过socket接口,区分来自不同的应用进程和网络连接的通信,实现数据传输的并发服务。(应用层在通过传输层传输的时候,传输层的TCP会同时遇到为多个应用进程提供并发服务的问题,多个TCP连接或多个应用进程可能需要同一个TCP连接,为了区别不同应用进程的连接,许多计算机为应用进程提供了套接字接口)
    • socket建立连接:socket是一个接口,它是可以指定传输层协议的,也就是说当他在指定TCP协议的时候建立的socket连接就是一个TCP连接,需要通过三次握手才能进行连接。从广义上讲:socket连接可以这样讲:
      • 服务器监听:说的是服务器套接字并不指定客户端套接字,它处于一个实时监听网络状态,等待客户端的请求,连接。
      • 客户端发送请求:客户端套接字在请求中声明套接字的描述和服务端的ip和端口号,然后向服务端套接字发送请求。
      • 连接确认:服务端套接字接收到客户端套接字发送来的请求后,想客户端套接字发送一个确认响应,并在这个响应中添加服务器套接字的描述,一旦客户端确认了这个描述,那么双方就正式的建立了连接,而测试服务器处于一个监听状态,等待着其他客户端套接字发送来的请求。
  1. socket接口是如何利用代码实现TCP连接和UDP连接的;

    • 代码实现TCP连接:首先在客户端创建socket对象,然后创建inputStream封装要传输的数据,然后在socket中通过getOutputStream获取输出流,然后通过写出io流的形式将数据写入到服务器当中去。在服务器中创建serviceSocket对象,然后通过serviceSocket对象中的accept方法获取socket对象,最后在socket对象中通过getInputStream方法获取数据。
    • 代码实现UDP连接: 首先在客户端创建DatagramSocket对象,然后创建DatagramPacket对象(他其实就是报包),这个对象创建的时候会需要传入四个参数,
      DatagramPacket p = new DatagramPacket(messageByte, msg_length, url, server_port);
      第一个参数为传递的数据data(不过是个字节数组,而且不能超过64k),第二个参数是数据的长度,第三个参数是网络地址(可以通过inetAddress.getByName这个方法传入一个ip就可以获得网络地址了),第四个参数是端口号。 然后socket对象.send(packet对象)发送报包就可以了。服务器端创建DatagramSocket对象,创建两个参数的DatagramPacket的空报包对象(只是创建一个字节数组),然后调用socket对象.receive(packet)来接受数据,最后调用packet.getData即可.
  2. HTTP通讯:

    • http协议:超文本传输协议,手机常用协议之一,是基于TCP协议之上的应用层协议。http1.0的时候是一个请求一个连接,请求结束后就会断开连接。http1.1的时候是已连接对应多个请求,多个请求可以重接执行,不用等一个请求结束在进行下一个请求,而http2.0同样是一个连接对应多个请求,并且在应用层和传输层增加了一个二进制的分帧层,这些帧对应逻辑流中的消息,并行的在同一个TCP连接上进行双向交流消息。
  3. socket和http的区别;

    • 形象的说http他就像一个轿车,提供了封装或者显示数据的具体形式,而socket是发动机,提供了网络通讯的能力,http他是一个协议,是基于TCP协议的,Tcp协议是基于ip协议的,而socket提供了针对TCP和UDP编程的接口。

推荐阅读更多精彩内容