1、定义

  • socket即套接字,是应用层 与 TCP/IP 协议族通信的中间软件抽象层,表现为一个封装了 TCP / IP协议族 的编程接口(API);

     

     说明: Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)

                  即:通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发

                  对用户来说,只需调用Socket去组织数据,以符合指定的协议,即可通信

  • 成对出现,一对套接字

          Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}

  • 一个 Socket 实例 唯一代表一个主机上的一个应用程序的通信链路

 

2、连接过程

     

 3、原理

       Socket的使用类型主要有两种:

  • 流套接字(streamsocket) :基于 TCP协议,采用 流的方式 提供可靠的字节流服务;
  • 数据报套接字(datagramsocket):基于 UDP协议,采用 数据报文 提供数据打包发送的服务;

4、socket与http

  •  Socket属于传输层,因为 TCP / IP协议属于传输层,解决的是数据如何在网络中传输的问题;
  • HTTP协议 属于 应用层,解决的是如何包装数据。

      具体:

  • Http:采用 请求—响应 方式。
  • 即建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。
    可理解为:是客户端有需要才进行通信
  • Socket:采用 服务器主动发送数据 的方式:
  • 即建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求
    可理解为:是服务器端有需要才进行通信

5、具体实例:基于TCP协议,手机连上同一个WIFI或使用热点

     5.1  加入权限:

<uses-permission android:name="android.permission.INTERNET" />

    5.2  布局实现

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="接收的消息:" />

    <TextView
        android:id="@+id/server_receive_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/server_send_content"
        android:layout_width="match_parent"
        android:layout_height="60dp" />

    <TextView
        android:id="@+id/server_send_button"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:gravity="center"
        android:text="发送消息" />

</LinearLayout>

    5.3  服务端实现:

public class ServerActivity extends Activity {
    private static final String TAG = "ServerActivity";

    public static final String SERVER_IP = "192.168.43.49";
    public static final int SERVER_PORT = 6668;

    private Handler mMainHandler;
    private ExecutorService mExecutor;
    private ServerSocket mServerSocket;
    private Socket mSocket;

    private TextView mReceiveMessage;
    private EditText mSendContent;
    private TextView mSendButton;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server);
        mReceiveMessage = findViewById(R.id.server_receive_message);
        mSendContent = findViewById(R.id.server_send_content);
        mSendButton = findViewById(R.id.server_send_button);
        mSendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = mSendContent.getText().toString().trim();
                sendMessage(message);
            }
        });

        mMainHandler = new Handler();
        mExecutor = Executors.newFixedThreadPool(2);

        try {
            mServerSocket = new ServerSocket(SERVER_PORT);
        } catch (IOException e) {
            Log.e(TAG, "create serverSocket fail, e = " + e.toString());
        }

        beginListen();
    }

    private void beginListen() {
        mExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    mSocket = mServerSocket.accept();
                    InputStream is = mSocket.getInputStream();

                    while (!mSocket.isClosed()) {
                        byte[] value = new byte[50];
                        is.read(value);
                        final String read = new String(value, "UTF-8");
                        if (!TextUtils.isEmpty(read)) {
                            Log.d(TAG, "receive message : " + read);
                            mMainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    mReceiveMessage.append("\n" + read);
                                }
                            });
                        }
                    }
                } catch (IOException e) {
                    Log.d(TAG, "listen fail, e = " + e.toString());
                    if (mSocket != null) {
                        try {
                            mSocket.close();
                        } catch (IOException e1) {

                        }
                    }
                }
            }
        });
    }

    private void sendMessage(final String message) {
        mExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    OutputStream os = mSocket.getOutputStream();
                    PrintWriter writer = new PrintWriter(os);
                    writer.write(message);
                    writer.flush();
                } catch (IOException e) {
                    Log.d(TAG, "sendMassage fail: e = " + e.toString());
                }
            }
        });
    }
}

    5.4 客户端实现:

public class ClientActivity extends Activity {
    private static final String TAG = "ClientActivity";

    private Handler mMainHandler;
    private ExecutorService mExecutor;
    private Socket mSocket;

    private TextView mReceiveMessage;
    private EditText mSendContent;
    private TextView mSendButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        mReceiveMessage = findViewById(R.id.client_receive_message);
        mSendContent = findViewById(R.id.client_send_content);
        mSendButton = findViewById(R.id.client_send_button);
        mSendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = mSendContent.getText().toString().trim();
                sendMessage(message);
            }
        });

        mMainHandler = new Handler();
        mExecutor = Executors.newFixedThreadPool(2);

        beginListen();
    }

    private void beginListen() {
        mExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    mSocket = new Socket(ServerActivity.SERVER_IP, ServerActivity.SERVER_PORT);

                    if (mSocket != null) {
                        InputStream is = mSocket.getInputStream();

                        while (!mSocket.isClosed()) {
                            byte[] value = new byte[50];
                            is.read(value);
                            final String read = new String(value, "UTF-8");
                            if (!TextUtils.isEmpty(read)) {
                                Log.d(TAG, "receive message : " + read);
                                mMainHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        mReceiveMessage.append("\n" + read);
                                    }
                                });
                            }
                        }
                    }
                } catch (IOException e) {
                    Log.d(TAG, "begin listen fail: e = " + e.toString());
                    if (mSocket != null) {
                        try {
                            mSocket.close();
                        } catch (IOException e1) {

                        }
                    }
                }
            }
        });
    }

    private void sendMessage(final String message) {
        mExecutor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    OutputStream os = mSocket.getOutputStream();
                    PrintWriter writer = new PrintWriter(os);
                    writer.write(message);
                    writer.flush();
                } catch (IOException e) {
                    Log.d(TAG, "sendMassage fail: e = " + e.toString());
                }
            }
        });
    }
}