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文件中注冊。靜態注冊的廣播,只要應用一直在系統中運行就會一直接收到廣播信息。
<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);
-
-
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編程的接口。