Android四大组件:
activity:
-
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()方法。
-
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存在。
-
如何保存和恢复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()调用之前。
-
两个activity之间跳转必然会执行那些方法;
- 两个activity,从A跳转至B,当B是一个对话框时或者透明窗体时,A会调用onPause()方法,B会调用onCreate(),onStart(),onResume(),当B覆盖A时,A会调用onStop()方法。
-
Android中activity,context,application之间有什么区别;
- 相同点:context是描述一个应用程序环境的信息,即上下文的意思,该类是一个抽象类(abstract class),Android有提供该抽象类的具体实现类(contextlml),activity和application都是context的子类。
- 不同点: 维护的生命周期不同。context维护的是当前activity的生命周期,而application维护的是整个项目的生命周期。
- 在使用context的时候,需要防止内存泄漏,需要注意几点:
- 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身的生命周期相同;
- 对于生命周期长的使用application context;
- 避免使用非静态内部类,尽量使用静态类,避免生命周期的问题,注意内部类对外部对象引用时导致的生命周期的变化。
-
如何退出activity?如何安全的退出已调用多个activity的application;
通常退出一个activity只需要按返回键,代码中直接调用finish()方法就行,
用数组记录住打开的每一个activity,在需要退出的时候,遍历,调用finish()方法关闭每一个activity即可。
发送特定的广播
在需要结束应用时,发送一个特定的广播,每个Activity 收到广播后,关闭即可。
//给某个activity 注册接受接受广播的意图
registerReceiver(receiver, filter)
//如果过接受到的是关闭activity 的广播就调用finish()方法把当前的activity finish()掉递归退出。在打开新的Activity时使用startActivityForResult,然后自己添加标志,在onActivityResult()中处理,递归关闭。
-
两个activity之间如何传递数据;
- 传递的方式有:intent,广播接收者,contentProvider,static静态数据(public static 成员变量),file文件存储,sharedPreferences,sqlite数据库.
service:
-
service是在main方法中执行,service中能否执行耗时操作;
- 默认情况下,如果没有显示的是指service所运行的进程,service和activity是运行在当前APP所在进程的主线程(main thread)中,service中不能进行耗时操作(网络操作,拷贝数据库,大文件),
- 特殊情况下,可以在清单文件中进行配置service所执行的进程,让service在其他进程中执行。
-
activity怎样和service绑定,怎样在activity中启动对应的service;
- activity通过bindService(intent service,ServiceConnection conn,int flags)跟service进行绑定,当绑定成功之后,service会将代理对象通过回调的方式传递给conn,这样就可以拿到Service提供的代理对象了。一般情况下, 如果想获取Service的服务对象那么就需要通过bindService(),比如,音乐播放器,第三方支付。
- activity还可以通过startService(),通常仅需要开启一个后台任务的时候用startService()。
-
service的生命周期;
- service有绑定模式和非绑定模式,以及两种的混合模式,不同的模式生命周期不同;
- 非绑定模式:当第一次调用startService的时候执行onCreate(),onStartCommand(),当service关闭的时候执行onDestory();
- 绑定模式:当第一次调用bindService()的时候,执行onCreate(),onBind(),当解除绑定的时候执行onUnbind(),onDestory()。
- 还需要注意的是service实例只会有一个,也就是说如果当前要启动的service已经存在了,那就不需用在启动service了,也就不会在调用onCreate()方法了。
- 一个service被多个客户所绑定,只有所有的绑定对象都执行了onBind()方法后该service才会销毁,但是如果有一个客户执行了onStart()方法,那么这个时候即使所有的service都执行了onBind()方法,service也不会销毁。
- service有绑定模式和非绑定模式,以及两种的混合模式,不同的模式生命周期不同;
-
什么是IntentService?有什么优点?
- intentService是service的子类,比起普通的service有了新的功能。普通的service存在两个问题:service不会启动一条单独的线程,service与他所在的应用位于同一个进程中;不能在service中直接处理耗时操作。
- intentService的特征:会创建独立的worker线程来处理所有的intent请求;会创建独立worker线程来处理onHandlerIntent()方法实现的代码,无需处理多线程问题;所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法来停止Service;为service的onBind()方法提供默认的实现,返回null;为service的onStartCommard()方法提供默认实现,将请求intent添加到请求队列中。
-
activity,service,intent之间的关系?
- activity负责用户界面的显示和交互,Service负责后台任务的处理,activity和service之间通过intent传递数据,activity和service都是context的子类contextWrapper的子类。
-
service中可以谈吐司吗?
- 可以的,但是得有个条件就是得有一个context上下文,由于service是context的子类,因此谈吐司是可以的。比如在service中完成任务的下载之后弹一个土司来提醒一下用户是完全可以的。
-
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:
-
什么是broadcast receiver,生命周期是什么?
- broadCast receiver 广播接收者,分为有序和无序,内部实现机制是通过Android系统的binder机制实现通信的。
- 无序广播:完全异步,逻辑上是可以被任何的广播接收者接收到,效率较高,但是无法一个接受者不能将处理结果传递给下一个接受者,并无法终止广播intent的传播。
- 有序广播:按照被接受者的优先级顺序,在被接受者中依次传播。
-
在mainfast和代码中如何注册和使用broadcast receiver。
-
静态注册:在mainfast.xml文件中注册。静态注册的广播,只要应用一直在系统中运行就会一直接收到广播信息。
-
动态注册:在代码中注册。动态注册的的广播,当注册的activity或者service销毁了,就接收不到广播了。
receiver = new BroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(CALL_ACTION); context.registerReceiver(receiver, intentFilter);
-
-
broadcastReceiver的生命周期;
- 广播接受者的生命周期很短暂,在接收到广播的时候创建,onReceive()方法结束之后销毁。
- 广播接收者中不要做一些耗时操作,否则会引起ANR,耗时较长的最好放在service中进行。
- 最好不要再广播接收者中创建子线程做耗时操作,因为广播接收者被销毁之后,进程就变成了空进程,很容易被系统清理掉。
contentProvider :
-
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[]); }
-
-
Android中的数据存储的方式?
- file文件,sharedPreference,conteneProvider,SQLite数据库,网络存储。
-
说出contentProvider,contentResolver, contentObserver之间的关系?
- contentProvider,内容提供者,用于对外提供数据;
- contentResolver,内容解析者,用于获取内容提供者提供的数据;contentResolver.notifyChange(uri)发出消息。
- contentObserver,内容观察者,用于监听内容数据的改变主状态。contentResolver.registercontentObserver()监听消息。
-
contentObserver内容观察者的作用及特点?
- contentObserver目的是观察特定的uri引起的数据库的变化。继而做一些相应的处理。
- 观察特定的uri的步骤:
- 创建特定的contentObserver派生类,必须重载父类的构造方法,必须重载onChange()方法去处理回调后的功能实现。
- 利用context.getContentResolover()获取contentResolover对象,接着调用registerContentObserver()方法去注册内容观察者;
- 在不需要时,需要手动的调用unregisterContentObserver()去取消注册。
intent:
-
intent传递数据可以传递那些类型数据?
- 八大基本数据类型和String以及数组形式都可以,还可以传递实现了Serializable和Parcelable接口的对象。
-
描述intent和intentFliter是什么?
- Android中通过intent对象来表示一条消息,通过intent可以实现各种系统组件的调用和激活。
- intentFliter可以理解为一个邮局或者一个信笺的分拣系统。
listview:
- 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 : 静止。
对不同的状态进行处理:分批加载数据,只关心静态状态:关心最后一个可见的条目,如果最后一个可见条目就是适配器里的最后一个,此时就可加载更多的数据,在每次加载的时候, 计算出滚动的数量,当滚动的数量大于等于总数量的时候,可以提示用户无更多的数据。
-
-
listview数据集改变之后,如何更新listview?
- 使用listview的adapter的notifyDataSetChange()方法,该方法会使listview重新绘制。
-
listview能否实现多种类型的条目?
- 可以,listview显示的每个条目都是通过baseAdapter的gitView(int position,View convertView,ViewGroup parent)来展示的,理论上可以让每个条目都是不同类型的view。
- 另外,adapter还提供了getViewTypeCount()和getItemViewType(int position)两个方法,在getView方法中可以根据不同的viewtype加载不同的布局文件。
-
listview如何跳转到指定位置?
- 可以通过lv.setSelection(listView.getPosition)方法。
-
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); } }
-
-
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); } }
- 通常情况下,在scrollView 重视不嵌套listview的,但是面试官要是问到这种问题的时候,回答是可以的,在scrollview 中添加一个listview会导致listview控件显示不全,通常只会显示一条,这是由于两个控件的滑动冲突导致的,所以:
-
如何刷新listview中item的单个数据,不刷新整个listview的数据?
- 修改单个item的数据,然后调用adapter的notifyDataSetChanged()方法进行刷新。或者直接用handler去更新,在adapter中创建一个handler,值发生改变的时候,handler就send一个message,更新ui。
recyclerView:
-
使用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有其自己默认的实现。
- 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这个类,然后针对自己的业务需求去抒写代码。
-
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());
-
recylerView的Adapter的写法,需要实现三个方法:
- onCreateViewHolder():这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
- onBindViewHolder():这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
- getItemCount():这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。
-
给RecyclerView的Item添加点击事件:
- 由于recylerView没有提供类似于listview的setOnItemClickListener()的方法来处理item的点击事件,因此只能模拟类似的方法, 使用的是在创建itemView的时候添加监听,就是在创建view的时候添加点击事件,然后在Adapter对对象中添加监听回调. 具体的做法是:首先自定义接口onRecylerViewItemClickListener,定义onItemClick()方法,在给方法中有两个参数,view和position,在给holder传入onRecylerViewItemClickListener参数,让holder实现View.OnClickListener,并在onClick方法中调用onRecylerViewItemClickListener.onItemClick()方法,通过传入的position来判断item的位置,从而实现每个item的点击事件.
-
给RecyclerView的Item添加下拉刷新:
- 通过SwipeRefreshLayout这个组件,去实现列表下拉刷新功能,通过设置下拉刷新的监听事件setOnRefreshListener()重写OnRefresh()方法,而设置上拉加载更多可以通过设置滑动事件监听来实现setOnScrollListener()重写onScrollStateChanged()方法.通过设置swipeRefreshView.setRefreshing为true来实现刷新.
socket通信与网络编程(TCP/UDP协议,http协议)
-
什么是网络编程:
- 网络编程是指两台设备之间实现数据传递的过程,也可以说是使用套接字完成不同进程之间的网络通讯的编程。要了解网络编程,需要先了解网络通讯,网络通讯分HTTP通讯和socket网络通讯,说到这需要先了解一下网络通讯的层级,网络通讯的层级一共有四层:最低层链路层,这里主要是硬件的接口,然后是网络层,这里用我们比较熟悉的IP协议,在然后是传输层,这里有TCP协议和UDP协议,最后就是应用层,HTTP协议(超文本传输协议)就在这一层,这里需要注意的是,HTTP是一种协议,而socket是一个接口。
-
传输层两大协议:TCP/UDP协议:
- UDP协议是一种用户数据报协议,是面向无连接的,数据传输不可靠的一种点对多点的通讯,也就是说UDP在传输数据前是不与对方建立连接的,对于接收到的数据也是不发送确认信号的,发送数据的一方也不会知道数据是否发送成功,也就无法再重新发送了。我们经常使用的“ping”命令来检测两台设备主机之间的TCP/IP通信是否正常,而这个“ping”就是 使用UDP协议,通过向对方主机发送UDP数据包,然后对方确认收到数据包,如果对方将数据包到达的纤细及时的返回回来,就说明两台设备主机之间的通讯是通的。
- TCP协议是一种传输控制协议,它是面向有连接的,数据传输可靠的一种通讯方式,它是通过三次握手来实现面向有连接的,而这三次握手指的是:
- 首先客户端发送一个空的数据报包给服务端,并且将客户端置为发送状态;
- 接着服务端接收到这这个空的数据报包,会相应客户端一个确认包,并将服务端置为接收状态;
3)客户端接收到服务端发送回来的响应,然后再向服务端发送一个确认包,一旦此包发送完毕,那么服务端就与客户端之间建立了长连接,并且双方都处于确认状态,而建立的这个长连接在理论上如果单方不主动去停止这个连接,这个连接就会一直存在,只要连接存在,服务器就可以和客户端近行数据的互传。
-
什么是socket通信:
- 说起socket,得要先知道套接字,套接字是TCP/IP网络通信的基本操作单元,主要包括三大要素:IP,协议,端口。在说socket,socket其实就是一堆套接字,它在客户端叫clientSocket,在服务端叫serviceSocket,socket其实就是方便TCP和UDP编程的一个接口,应用层和传输层通过socket接口,区分来自不同的应用进程和网络连接的通信,实现数据传输的并发服务。(应用层在通过传输层传输的时候,传输层的TCP会同时遇到为多个应用进程提供并发服务的问题,多个TCP连接或多个应用进程可能需要同一个TCP连接,为了区别不同应用进程的连接,许多计算机为应用进程提供了套接字接口)
- socket建立连接:socket是一个接口,它是可以指定传输层协议的,也就是说当他在指定TCP协议的时候建立的socket连接就是一个TCP连接,需要通过三次握手才能进行连接。从广义上讲:socket连接可以这样讲:
-
- 服务器监听:说的是服务器套接字并不指定客户端套接字,它处于一个实时监听网络状态,等待客户端的请求,连接。
- 客户端发送请求:客户端套接字在请求中声明套接字的描述和服务端的ip和端口号,然后向服务端套接字发送请求。
- 连接确认:服务端套接字接收到客户端套接字发送来的请求后,想客户端套接字发送一个确认响应,并在这个响应中添加服务器套接字的描述,一旦客户端确认了这个描述,那么双方就正式的建立了连接,而测试服务器处于一个监听状态,等待着其他客户端套接字发送来的请求。
-
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即可.
-
HTTP通讯:
- http协议:超文本传输协议,手机常用协议之一,是基于TCP协议之上的应用层协议。http1.0的时候是一个请求一个连接,请求结束后就会断开连接。http1.1的时候是已连接对应多个请求,多个请求可以重接执行,不用等一个请求结束在进行下一个请求,而http2.0同样是一个连接对应多个请求,并且在应用层和传输层增加了一个二进制的分帧层,这些帧对应逻辑流中的消息,并行的在同一个TCP连接上进行双向交流消息。
-
socket和http的区别;
- 形象的说http他就像一个轿车,提供了封装或者显示数据的具体形式,而socket是发动机,提供了网络通讯的能力,http他是一个协议,是基于TCP协议的,Tcp协议是基于ip协议的,而socket提供了针对TCP和UDP编程的接口。