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()); } } }); } }