UDP协议和TCP协议是互联网使用最广的两种协议都是基于IP的协议。第一个区别是UDP协议是一个不太靠谱的协议,UDP协议把数据都打成数据包,数据包上自带通讯地址,也就是说我要把这个数据包发送到网络上的哪一个地址,通过网络把这个数据包发送出去,至于这个数据包是否发送到目的地,是否服务器端接收到了这个数据包,这个协议并不保证,就像中国的邮政,你是把信寄出去了,但是邮政系统不保证对方能收到你寄送的信。TCP发送数据的时候要求接收方接收到数据之后给一个回应,也就是你是否收到了,TCP可靠一些,当我们发送一些比较重要的数据的时候一般都使用TCP协议。另外一个区别是UDP协议发送的一个数据包它的容量是有限的,而TCP协议则没有这样一个限制。并不是说UDP协议一定就不如TCP协议,在不同的领域有不同是使用,UDP协议好处是速度相对快些。TCP协议相对慢些。
-Socket通讯流程
应用程序通过“套接字”也就是Socket可以选择这两种协议当中的一种,你可以选择用UDP发送数据,也可以选择用TCP发送数据,数据发送出去通过“通信信道”也就是IP的基础网络,来到服务器端(接收端),就可以接收到数据了。发送数据的时候用UDP协议,接收的时候也要用UDP协议,发送数据的时候用TCP协议,接收的时候也要用TCP协议,在发送的时候指定接收端的IP地址和端口号就可以了,究竟数据包或数据是如何发送的,框架已经帮我们封装好了,我们不去关心它了。
一:TCP协议通讯模型 1:工作流程
首先有两部分客户端和服务器端,客户端需要Socket这个类的对象,而服务器端需要ServerSocket这个类的对象,由客户端Socket发送一个请求,服务器端的ServerSocket在计算机的某一个端口号上进行监听,监听客户端发送的请求之后,那么客户端和服务器端的一个通讯通道就建立起来了,这时候呢既可以从客户端向服务器端发送数据,服务器端也可以给客户端相应的响应。在客户端发送数据的时候我们需要用到IO流里面的OutputStream,通过这个OutputStream把数据发送给服务器端,服务器端用InputStream来读取客户端当中用OutputStream所写入的数据。生活举例:就像双方男女朋友打电话一样,男孩(客户端)说话(数据)通过听筒发送到电话网络中去,当男孩说话的时候就相当于咱们这里的通过OutputStream向互联网中写入数据,而作为接听的这个女孩(服务器端)那么男孩(客户端)说的内容就是女孩(服务器端)听到的内容,那么就是说服务器端可以通过InputStream把客户端当中通过OutputStream所写入的数据给它读取出来,反之亦然,如果服务器端想向客户端发送数据,那么就使用OutputStream写出数据,在客户端通过InputStream把服务器端当中通过OutputStream所写入的数据给它读取出来。就像打电话一样,你说的就是我听的,你听的就是我说的。 二:通过基于TCP协议发送和读取数据
好了我们看看在Android中如何使用Socket的。
Android中使用Socket模型
服务器端:
接下来是客服端程序:
- package com.Aina.Android;
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.InputStreamReader;
- import java.io.OutputStreamWriter;
- import java.io.PrintWriter;
- import java.net.Socket;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.content.DialogInterface;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- public class Test extends Activity implements Runnable {
- /** Called when the activity is first created. */
- private TextView tv_msg = null;
- private EditText ed_msg = null;
- private Button btn_send = null;
- private Button btn_login = null;
- private static final String HOST = "192.168.0.132";
- private static final int PORT = 9999;
- private Socket socket = null;
- private BufferedReader in = null;
- private PrintWriter out = null;
- private String content = "";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- tv_msg = (TextView) this.findViewById(R.id.TextView);
- ed_msg = (EditText) this.findViewById(R.id.EditText01);
- btn_login = (Button) this.findViewById(R.id.Button01);
- btn_send = (Button) this.findViewById(R.id.Button02);
- try {
- socket = new Socket(HOST, PORT);
- in = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));
- out = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(socket.getOutputStream())),
- true);
- } catch (Exception ex) {
- ex.printStackTrace();
- ShowDialog("登陆异常:" + ex.getMessage());
- }
- btn_send.setOnClickListener(new Button.OnClickListener() {
- public void onClick(View v) {
- // TODO Auto-generated method stub
- String msg = ed_msg.getText().toString();
- if (socket.isConnected()) {
- if (!socket.isOutputShutdown()) {
- out.println(msg);
- }
- }
- }
- });
- new Thread(this).start();
- }
- public void ShowDialog(String msg) {
- new AlertDialog.Builder(this).setTitle("提示").setMessage(msg)
- .setPositiveButton("OK", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- // TODO Auto-generated method stub
- }
- }).show();
- }
- public void run() {
- try {
- while (true) {
- if(socket.isConnected()){
- if(!socket.isInputShutdown()){
- if ((content = in.readLine()) != null) {
- Log.i("TAG", "++ "+content);
- content += "\n";
- mHandler.sendMessage(mHandler.obtainMessage());
- }else{
-
- }
- }
- }
-
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- public Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- Log.i("TAG", "-- "+msg);
- tv_msg.setText(tv_msg.getText().toString() + content);
- }
- };
- }
接下来是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">
- <TextView android:id="@+id/TextView" android:singleLine="false"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
- <EditText android:hint="content" android:id="@+id/EditText01"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </EditText>
- <Button android:text="login" android:id="@+id/Button01"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Button>
- <Button android:text="send" android:id="@+id/Button02"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </Button>
- </LinearLayout>
问题解决&处理
1 出现02-07 12:16:11.507: W/System.err(1173): java.net.BindException: Permission denied错误
按照如下方法解决,端口号取大于1024的。并且加上android.permission.INTERNET权限。
1)Either root your phone, modify the firmware, or don‘t bind to ports lower than 1024. That‘s a Linux thing more than an Android thing.
2)Try add permission android.permission.INTERNET it worked for me
2 使用客户端连接时,出现java.net.ConnectException: Connection refused错误
将与安卓模拟器通讯的ip地址改为10.0.0.2。错误取消。